diff --git a/models/user/badge.go b/models/user/badge.go
index e143d3de8d..097a7bd16f 100644
--- a/models/user/badge.go
+++ b/models/user/badge.go
@@ -6,11 +6,9 @@ package user
 import (
 	"context"
 	"fmt"
-	"net/url"
 	"strings"
 
 	"code.gitea.io/gitea/models/db"
-	"code.gitea.io/gitea/modules/setting"
 
 	"xorm.io/builder"
 	"xorm.io/xorm"
@@ -36,10 +34,6 @@ func init() {
 	db.RegisterModel(new(UserBadge))
 }
 
-func AdminCreateBadge(ctx context.Context, badge *Badge) error {
-	return CreateBadge(ctx, badge)
-}
-
 // GetUserBadges returns the user's badges.
 func GetUserBadges(ctx context.Context, u *User) ([]*Badge, int64, error) {
 	sess := db.GetEngine(ctx).
@@ -52,13 +46,13 @@ func GetUserBadges(ctx context.Context, u *User) ([]*Badge, int64, error) {
 	return badges, count, err
 }
 
-// GetBadgeUsers returns the badges users.
+// GetBadgeUsers returns the users that have a specific badge.
 func GetBadgeUsers(ctx context.Context, b *Badge) ([]*User, int64, error) {
 	sess := db.GetEngine(ctx).
 		Select("`user`.*").
 		Join("INNER", "user_badge", "`user_badge`.user_id=user.id").
-		Where("user_badge.badge_id=?", b.ID)
-
+		Join("INNER", "badge", "`user_badge`.badge_id=badge.id").
+		Where("badge.slug=?", b.Slug)
 	users := make([]*User, 0, 8)
 	count, err := sess.FindAndCount(&users)
 	return users, count, err
@@ -66,20 +60,13 @@ func GetBadgeUsers(ctx context.Context, b *Badge) ([]*User, int64, error) {
 
 // CreateBadge creates a new badge.
 func CreateBadge(ctx context.Context, badge *Badge) error {
-	isExist, err := IsBadgeExist(ctx, 0, badge.Slug)
-
-	if err != nil {
-		return err
-	} else if isExist {
-		return ErrBadgeAlreadyExist{badge.Slug}
-	}
-
-	_, err = db.GetEngine(ctx).Insert(badge)
+	// this will fail if the badge already exists due to the UNIQUE constraint
+	_, err := db.GetEngine(ctx).Insert(badge)
 
 	return err
 }
 
-// GetBadge returns a badge
+// GetBadge returns a specific badge
 func GetBadge(ctx context.Context, slug string) (*Badge, error) {
 	badge := new(Badge)
 	has, err := db.GetEngine(ctx).Where("slug=?", slug).Get(badge)
@@ -89,22 +76,9 @@ func GetBadge(ctx context.Context, slug string) (*Badge, error) {
 	return badge, err
 }
 
-// GetBadgeByID returns a badge
-func GetBadgeByID(ctx context.Context, id int64) (*Badge, error) {
-	badge := new(Badge)
-	has, err := db.GetEngine(ctx).Where("id=?", id).Get(badge)
-	if err != nil {
-		return nil, err
-	} else if !has {
-		return nil, ErrBadgeNotExist{ID: id}
-	}
-
-	return badge, err
-}
-
 // UpdateBadge updates a badge based on its slug.
 func UpdateBadge(ctx context.Context, badge *Badge) error {
-	_, err := db.GetEngine(ctx).Where("id=?", badge.ID).Cols("slug", "description", "image_url").Update(badge)
+	_, err := db.GetEngine(ctx).Where("slug=?", badge.Slug).Cols("description", "image_url").Update(badge)
 	return err
 }
 
@@ -114,24 +88,8 @@ func DeleteBadge(ctx context.Context, badge *Badge) error {
 	return err
 }
 
-// DeleteUserBadgeRecord deletes a user badge record.
-func DeleteUserBadgeRecord(ctx context.Context, badge *Badge) error {
-	userBadge := &UserBadge{
-		BadgeID: badge.ID,
-	}
-	_, err := db.GetEngine(ctx).Where("badge_id=?", userBadge.BadgeID).Delete(userBadge)
-	return err
-}
-
 // AddUserBadge adds a badge to a user.
 func AddUserBadge(ctx context.Context, u *User, badge *Badge) error {
-	isExist, err := IsBadgeUserExist(ctx, u.ID, badge.ID)
-	if err != nil {
-		return err
-	} else if isExist {
-		return ErrBadgeAlreadyExist{}
-	}
-
 	return AddUserBadges(ctx, u, []*Badge{badge})
 }
 
@@ -140,11 +98,11 @@ func AddUserBadges(ctx context.Context, u *User, badges []*Badge) error {
 	return db.WithTx(ctx, func(ctx context.Context) error {
 		for _, badge := range badges {
 			// hydrate badge and check if it exists
-			has, err := db.GetEngine(ctx).Where("id=?", badge.ID).Get(badge)
+			has, err := db.GetEngine(ctx).Where("slug=?", badge.Slug).Get(badge)
 			if err != nil {
 				return err
 			} else if !has {
-				return ErrBadgeNotExist{ID: badge.ID}
+				return ErrBadgeNotExist{Slug: badge.Slug}
 			}
 			if err := db.Insert(ctx, &UserBadge{
 				BadgeID: badge.ID,
@@ -162,11 +120,19 @@ func RemoveUserBadge(ctx context.Context, u *User, badge *Badge) error {
 	return RemoveUserBadges(ctx, u, []*Badge{badge})
 }
 
-// RemoveUserBadges removes badges from a user.
+// RemoveUserBadges removes specific badges from a user.
 func RemoveUserBadges(ctx context.Context, u *User, badges []*Badge) error {
 	return db.WithTx(ctx, func(ctx context.Context) error {
 		for _, badge := range badges {
-			if _, err := db.GetEngine(ctx).Delete(&UserBadge{BadgeID: badge.ID, UserID: u.ID}); err != nil {
+			subQuery := builder.
+				Select("id").
+				From("badge").
+				Where(builder.Eq{"slug": badge.Slug})
+
+			if _, err := db.GetEngine(ctx).
+				Where("`user_badge`.user_id=?", u.ID).
+				And(builder.In("badge_id", subQuery)).
+				Delete(&UserBadge{}); err != nil {
 				return err
 			}
 		}
@@ -180,28 +146,6 @@ func RemoveAllUserBadges(ctx context.Context, u *User) error {
 	return err
 }
 
-// HTMLURL returns the badges full link.
-func (u *Badge) HTMLURL() string {
-	return setting.AppURL + url.PathEscape(u.Slug)
-}
-
-// IsBadgeExist checks if given badge slug exist,
-// it is used when creating/updating a badge slug
-func IsBadgeExist(ctx context.Context, uid int64, slug string) (bool, error) {
-	if len(slug) == 0 {
-		return false, nil
-	}
-	return db.GetEngine(ctx).
-		Where("slug!=?", uid).
-		Get(&Badge{Slug: strings.ToLower(slug)})
-}
-
-// IsBadgeUserExist checks if given badge id, uid exist,
-func IsBadgeUserExist(ctx context.Context, uid, bid int64) (bool, error) {
-	return db.GetEngine(ctx).
-		Get(&UserBadge{UserID: uid, BadgeID: bid})
-}
-
 // SearchBadgeOptions represents the options when fdin badges
 type SearchBadgeOptions struct {
 	db.ListOptions
diff --git a/models/user/error.go b/models/user/error.go
index 1c65ea7f16..88986ee93c 100644
--- a/models/user/error.go
+++ b/models/user/error.go
@@ -131,7 +131,6 @@ func (err ErrBadgeAlreadyExist) Unwrap() error {
 // ErrBadgeNotExist represents a "BadgeNotExist" kind of error.
 type ErrBadgeNotExist struct {
 	Slug string
-	ID   int64
 }
 
 // IsErrBadgeNotExist checks if an error is a ErrBadgeNotExist.
@@ -141,7 +140,7 @@ func IsErrBadgeNotExist(err error) bool {
 }
 
 func (err ErrBadgeNotExist) Error() string {
-	return fmt.Sprintf("badge does not exist [slug: %s | id: %d]", err.Slug, err.ID)
+	return fmt.Sprintf("badge does not exist [slug: %s]", err.Slug)
 }
 
 // Unwrap unwraps this error as a ErrNotExist error
diff --git a/modules/validation/binding.go b/modules/validation/binding.go
index 906cbeb1e4..dadcdb1edb 100644
--- a/modules/validation/binding.go
+++ b/modules/validation/binding.go
@@ -26,8 +26,8 @@ const (
 	ErrUsername = "UsernameError"
 	// ErrInvalidGroupTeamMap is returned when a group team mapping is invalid
 	ErrInvalidGroupTeamMap = "InvalidGroupTeamMap"
-	ErrInvalidImageURL     = "InvalidImageURL"
-	ErrInvalidSlug         = "InvalidSlug"
+	// ErrInvalidSlug is returned when a slug is invalid
+	ErrInvalidSlug = "InvalidSlug"
 )
 
 // AddBindingRules adds additional binding rules
@@ -40,7 +40,6 @@ func AddBindingRules() {
 	addGlobOrRegexPatternRule()
 	addUsernamePatternRule()
 	addValidGroupTeamMapRule()
-	addValidImageURLBindingRule()
 	addSlugPatternRule()
 }
 
@@ -98,24 +97,6 @@ func addValidSiteURLBindingRule() {
 	})
 }
 
-func addValidImageURLBindingRule() {
-	// URL validation rule
-	binding.AddRule(&binding.Rule{
-		IsMatch: func(rule string) bool {
-			return strings.HasPrefix(rule, "ValidImageUrl")
-		},
-		IsValid: func(errs binding.Errors, name string, val any) (bool, binding.Errors) {
-			str := fmt.Sprintf("%v", val)
-			if len(str) != 0 && !IsValidImageURL(str) {
-				errs.Add([]string{name}, ErrInvalidImageURL, "ImageURL")
-				return false, errs
-			}
-
-			return true, errs
-		},
-	})
-}
-
 func addSlugPatternRule() {
 	binding.AddRule(&binding.Rule{
 		IsMatch: func(rule string) bool {
diff --git a/modules/validation/helpers.go b/modules/validation/helpers.go
index 9925ea0ef5..1fba01b2a0 100644
--- a/modules/validation/helpers.go
+++ b/modules/validation/helpers.go
@@ -6,7 +6,6 @@ package validation
 import (
 	"net"
 	"net/url"
-	"path/filepath"
 	"regexp"
 	"strings"
 
@@ -51,29 +50,6 @@ func IsValidSiteURL(uri string) bool {
 	return false
 }
 
-// IsValidImageURL checks if URL is valid and points to an image
-func IsValidImageURL(uri string) bool {
-	u, err := url.ParseRequestURI(uri)
-	if err != nil {
-		return false
-	}
-
-	if !validPort(portOnly(u.Host)) {
-		return false
-	}
-
-	for _, scheme := range setting.Service.ValidSiteURLSchemes {
-		if scheme == u.Scheme {
-			// Check if the path has an image file extension
-			ext := strings.ToLower(filepath.Ext(u.Path))
-			if ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".bmp" || ext == ".svg" || ext == ".webp" {
-				return true
-			}
-		}
-	}
-	return false
-}
-
 // IsEmailDomainListed checks whether the domain of an email address
 // matches a list of domains
 func IsEmailDomainListed(globs []glob.Glob, email string) bool {
diff --git a/modules/web/middleware/binding.go b/modules/web/middleware/binding.go
index d086c2047d..6a7582ed8f 100644
--- a/modules/web/middleware/binding.go
+++ b/modules/web/middleware/binding.go
@@ -138,8 +138,6 @@ func Validate(errs binding.Errors, data map[string]any, f Form, l translation.Lo
 				data["ErrorMsg"] = trName + l.TrString("form.username_error")
 			case validation.ErrInvalidGroupTeamMap:
 				data["ErrorMsg"] = trName + l.TrString("form.invalid_group_team_map_error", errs[0].Message)
-			case validation.ErrInvalidImageURL:
-				data["ErrorMsg"] = l.TrString("form.invalid_image_url_error")
 			case validation.ErrInvalidSlug:
 				data["ErrorMsg"] = l.TrString("form.invalid_slug_error")
 			default:
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index e698a1b5ac..6c4c641077 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -3032,7 +3032,7 @@ badges.edit_badge = Edit Badge
 badges.update_badge = Update Badge
 badges.delete_badge = Delete Badge
 badges.delete_badge_desc = Are you sure you want to permanently delete this badge?
-badges.users_with_badge = Users with Badge (%d)
+badges.users_with_badge = Users with Badge (%s)
 badges.add_user = Add User
 badges.remove_user = Remove User
 badges.delete_user_desc = Are you sure you want to remove this badge from the user?
diff --git a/routers/web/admin/badges.go b/routers/web/admin/badges.go
index c96c43761f..4bcf20cf30 100644
--- a/routers/web/admin/badges.go
+++ b/routers/web/admin/badges.go
@@ -1,10 +1,10 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
 // Copyright 2024 The Gitea Authors.
 // SPDX-License-Identifier: MIT
 
 package admin
 
 import (
+	"fmt"
 	"net/http"
 	"net/url"
 	"strconv"
@@ -86,11 +86,8 @@ func NewBadgePost(ctx *context.Context) {
 		return
 	}
 
-	if err := user_model.AdminCreateBadge(ctx, b); err != nil {
+	if err := user_model.CreateBadge(ctx, b); err != nil {
 		switch {
-		case user_model.IsErrBadgeAlreadyExist(err):
-			ctx.Data["Err_Slug"] = true
-			ctx.RenderWithErr(ctx.Tr("form.slug_been_taken"), tplBadgeNew, &form)
 		default:
 			ctx.ServerError("CreateBadge", err)
 		}
@@ -104,17 +101,16 @@ func NewBadgePost(ctx *context.Context) {
 }
 
 func prepareBadgeInfo(ctx *context.Context) *user_model.Badge {
-	b, err := user_model.GetBadgeByID(ctx, ctx.ParamsInt64(":badgeid"))
+	b, err := user_model.GetBadge(ctx, ctx.PathParam(":badge_slug"))
 	if err != nil {
 		if user_model.IsErrBadgeNotExist(err) {
 			ctx.Redirect(setting.AppSubURL + "/admin/badges")
 		} else {
-			ctx.ServerError("GetBadgeByID", err)
+			ctx.ServerError("GetBadge", err)
 		}
 		return nil
 	}
 	ctx.Data["Badge"] = b
-	ctx.Data["Image"] = b.ImageURL != ""
 
 	users, count, err := user_model.GetBadgeUsers(ctx, b)
 	if err != nil {
@@ -171,13 +167,10 @@ func EditBadgePost(ctx *context.Context) {
 	}
 
 	if form.Slug != "" {
-		if err := user_service.RenameBadge(ctx, ctx.Data["Badge"].(*user_model.Badge), form.Slug); err != nil {
+		if err := user_service.UpdateBadge(ctx, ctx.Data["Badge"].(*user_model.Badge)); err != nil {
 			switch {
-			case user_model.IsErrBadgeAlreadyExist(err):
-				ctx.Data["Err_Slug"] = true
-				ctx.RenderWithErr(ctx.Tr("form.slug_been_taken"), tplBadgeEdit, &form)
 			default:
-				ctx.ServerError("RenameBadge", err)
+				ctx.ServerError("UpdateBadge", err)
 			}
 			return
 		}
@@ -194,18 +187,18 @@ func EditBadgePost(ctx *context.Context) {
 	log.Trace("Badge updated by admin (%s): %s", ctx.Doer.Name, b.Slug)
 
 	ctx.Flash.Success(ctx.Tr("admin.badges.update_success"))
-	ctx.Redirect(setting.AppSubURL + "/admin/badges/" + url.PathEscape(ctx.Params(":badgeid")))
+	ctx.Redirect(setting.AppSubURL + "/admin/badges/" + url.PathEscape(ctx.PathParam(":badge_slug")))
 }
 
 // DeleteBadge response for deleting a badge
 func DeleteBadge(ctx *context.Context) {
-	b, err := user_model.GetBadgeByID(ctx, ctx.ParamsInt64(":badgeid"))
+	b, err := user_model.GetBadge(ctx, ctx.PathParam(":badge_slug"))
 	if err != nil {
-		ctx.ServerError("GetBadgeByID", err)
+		ctx.ServerError("GetBadge", err)
 		return
 	}
 
-	if err = user_service.DeleteBadge(ctx, b, true); err != nil {
+	if err = user_service.DeleteBadge(ctx, b); err != nil {
 		ctx.ServerError("DeleteBadge", err)
 		return
 	}
@@ -217,10 +210,10 @@ func DeleteBadge(ctx *context.Context) {
 }
 
 func BadgeUsers(ctx *context.Context) {
-	ctx.Data["Title"] = ctx.Tr("admin.badges.users_with_badge", ctx.ParamsInt64(":badgeid"))
+	ctx.Data["Title"] = ctx.Tr("admin.badges.users_with_badge", ctx.PathParam(":badge_slug"))
 	ctx.Data["PageIsAdminBadges"] = true
 
-	users, _, err := user_model.GetBadgeUsers(ctx, &user_model.Badge{ID: ctx.ParamsInt64(":badgeid")})
+	users, _, err := user_model.GetBadgeUsers(ctx, &user_model.Badge{Slug: ctx.PathParam(":badge_slug")})
 	if err != nil {
 		ctx.ServerError("GetBadgeUsers", err)
 		return
@@ -246,7 +239,7 @@ func BadgeUsersPost(ctx *context.Context) {
 		return
 	}
 
-	if err = user_model.AddUserBadge(ctx, u, &user_model.Badge{ID: ctx.ParamsInt64(":badgeid")}); err != nil {
+	if err = user_model.AddUserBadge(ctx, u, &user_model.Badge{Slug: ctx.PathParam(":badge_slug")}); err != nil {
 		if user_model.IsErrBadgeNotExist(err) {
 			ctx.Flash.Error(ctx.Tr("admin.badges.not_found"))
 		} else {
@@ -261,21 +254,21 @@ func BadgeUsersPost(ctx *context.Context) {
 
 // DeleteBadgeUser delete a badge from a user
 func DeleteBadgeUser(ctx *context.Context) {
-	if user, err := user_model.GetUserByID(ctx, ctx.FormInt64("id")); err != nil {
+	user, err := user_model.GetUserByID(ctx, ctx.FormInt64("id"))
+	if err != nil {
 		if user_model.IsErrUserNotExist(err) {
 			ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
 		} else {
 			ctx.ServerError("GetUserByName", err)
 			return
 		}
+	}
+	if err := user_model.RemoveUserBadge(ctx, user, &user_model.Badge{Slug: ctx.PathParam(":badge_slug")}); err == nil {
+		ctx.Flash.Success(ctx.Tr("admin.badges.user_remove_success"))
 	} else {
-		if err := user_model.RemoveUserBadge(ctx, user, &user_model.Badge{ID: ctx.ParamsInt64(":badgeid")}); err == nil {
-			ctx.Flash.Success(ctx.Tr("admin.badges.user_remove_success"))
-		} else {
-			ctx.Flash.Error("DeleteUser: " + err.Error())
-			return
-		}
+		ctx.Flash.Error("DeleteUser: " + err.Error())
+		return
 	}
 
-	ctx.JSONRedirect(setting.AppSubURL + "/admin/badges/" + ctx.Params(":badgeid") + "/users")
+	ctx.JSONRedirect(fmt.Sprintf("%s/admin/badges/%s/users", setting.AppSubURL, ctx.PathParam(":badge_slug")))
 }
diff --git a/routers/web/explore/badge.go b/routers/web/explore/badge.go
index fd16f38015..cc6bd2dc63 100644
--- a/routers/web/explore/badge.go
+++ b/routers/web/explore/badge.go
@@ -9,16 +9,13 @@ import (
 	"code.gitea.io/gitea/models/db"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/base"
-	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
-	"code.gitea.io/gitea/modules/sitemap"
 	"code.gitea.io/gitea/services/context"
 )
 
 func RenderBadgeSearch(ctx *context.Context, opts *user_model.SearchBadgeOptions, tplName base.TplName) {
 	// Sitemap index for sitemap paths
-	opts.Page = int(ctx.ParamsInt64("idx"))
-	isSitemap := ctx.Params("idx") != ""
+	opts.Page = int(ctx.PathParamInt64("idx"))
 	if opts.Page <= 1 {
 		opts.Page = ctx.FormInt("page")
 	}
@@ -26,10 +23,6 @@ func RenderBadgeSearch(ctx *context.Context, opts *user_model.SearchBadgeOptions
 		opts.Page = 1
 	}
 
-	if isSitemap {
-		opts.PageSize = setting.UI.SitemapPagingNum
-	}
-
 	var (
 		badges  []*user_model.Badge
 		count   int64
@@ -69,17 +62,6 @@ func RenderBadgeSearch(ctx *context.Context, opts *user_model.SearchBadgeOptions
 			return
 		}
 	}
-	if isSitemap {
-		m := sitemap.NewSitemap()
-		for _, item := range badges {
-			m.Add(sitemap.URL{URL: item.HTMLURL()})
-		}
-		ctx.Resp.Header().Set("Content-Type", "text/xml")
-		if _, err := m.WriteTo(ctx.Resp); err != nil {
-			log.Error("Failed writing sitemap: %v", err)
-		}
-		return
-	}
 
 	ctx.Data["Keyword"] = opts.Keyword
 	ctx.Data["Total"] = count
diff --git a/routers/web/web.go b/routers/web/web.go
index f9da0cc7d6..e9d05ec8b8 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -725,11 +725,11 @@ func registerRoutes(m *web.Router) {
 		m.Group("/badges", func() {
 			m.Get("", admin.Badges)
 			m.Combo("/new").Get(admin.NewBadge).Post(web.Bind(forms.AdminCreateBadgeForm{}), admin.NewBadgePost)
-			m.Get("/{badgeid}", admin.ViewBadge)
-			m.Combo("/{badgeid}/edit").Get(admin.EditBadge).Post(web.Bind(forms.AdminCreateBadgeForm{}), admin.EditBadgePost)
-			m.Post("/{badgeid}/delete", admin.DeleteBadge)
-			m.Combo("/{badgeid}/users").Get(admin.BadgeUsers).Post(admin.BadgeUsersPost)
-			m.Post("/{badgeid}/users/delete", admin.DeleteBadgeUser)
+			m.Get("/{badge_slug}", admin.ViewBadge)
+			m.Combo("/{badge_slug}/edit").Get(admin.EditBadge).Post(web.Bind(forms.AdminCreateBadgeForm{}), admin.EditBadgePost)
+			m.Post("/{badge_slug}/delete", admin.DeleteBadge)
+			m.Combo("/{badge_slug}/users").Get(admin.BadgeUsers).Post(admin.BadgeUsersPost)
+			m.Post("/{badge_slug}/users/delete", admin.DeleteBadgeUser)
 		})
 
 		m.Group("/emails", func() {
diff --git a/services/user/badge.go b/services/user/badge.go
index e8a6a65ebd..d4c6fe88ef 100644
--- a/services/user/badge.go
+++ b/services/user/badge.go
@@ -11,51 +11,22 @@ import (
 	user_model "code.gitea.io/gitea/models/user"
 )
 
-// RenameBadge changes the slug of a badge.
-func RenameBadge(ctx context.Context, b *user_model.Badge, newSlug string) error {
-	if newSlug == b.Slug {
-		return nil
-	}
-
-	olderSlug := b.Slug
-
+// UpdateBadgeDescription changes the description and/or image of a badge
+func UpdateBadge(ctx context.Context, b *user_model.Badge) error {
 	ctx, committer, err := db.TxContext(ctx)
 	if err != nil {
 		return err
 	}
 	defer committer.Close()
 
-	isExist, err := user_model.IsBadgeExist(ctx, b.ID, newSlug)
-	if err != nil {
-		return err
-	}
-	if isExist {
-		return user_model.ErrBadgeAlreadyExist{
-			Slug: newSlug,
-		}
-	}
-
-	b.Slug = newSlug
 	if err := user_model.UpdateBadge(ctx, b); err != nil {
-		b.Slug = olderSlug
 		return err
 	}
-	if err = committer.Commit(); err != nil {
-		b.Slug = olderSlug
-		return err
-	}
-	return nil
+	return committer.Commit()
 }
 
-// DeleteBadge completely and permanently deletes everything of a badge
-func DeleteBadge(ctx context.Context, b *user_model.Badge, purge bool) error {
-	if purge {
-		err := user_model.DeleteUserBadgeRecord(ctx, b)
-		if err != nil {
-			return err
-		}
-	}
-
+// DeleteBadge remove record of badge in the database
+func DeleteBadge(ctx context.Context, b *user_model.Badge) error {
 	ctx, committer, err := db.TxContext(ctx)
 	if err != nil {
 		return err
diff --git a/templates/admin/badge/edit.tmpl b/templates/admin/badge/edit.tmpl
index ef5bd1985e..2c6e197a7a 100644
--- a/templates/admin/badge/edit.tmpl
+++ b/templates/admin/badge/edit.tmpl
@@ -8,9 +8,9 @@
 				{{template "base/disable_form_autofill"}}
 				{{.CsrfTokenHtml}}
 
-				<div class="required non-local field {{if .Err_Slug}}error{{end}}">
+				<div class="non-local field {{if .Err_Slug}}error{{end}}" disabled=disabled>
 					<label for="slug">{{ctx.Locale.Tr "admin.badges.slug"}}</label>
-					<input autofocus required id="slug" name="slug" value="{{.Badge.Slug}}">
+					<input disabled=disabled id="slug" name="slug" value="{{.Badge.Slug}}">
 				</div>
 				<div class="field {{if .Err_Description}}error{{end}}">
 					<label for="description">{{ctx.Locale.Tr "admin.badges.description"}}</label>
diff --git a/templates/admin/badge/list.tmpl b/templates/admin/badge/list.tmpl
index c0480f3f57..0f4db0fc9e 100644
--- a/templates/admin/badge/list.tmpl
+++ b/templates/admin/badge/list.tmpl
@@ -40,11 +40,6 @@
 						</th>
 						<th>{{ctx.Locale.Tr "admin.badges.description"}}</th>
 						<th></th>
-						<th></th>
-						<th></th>
-						<th></th>
-						<th></th>
-						<th></th>
 					</tr>
 				</thead>
 				<tbody>
@@ -52,18 +47,13 @@
 						<tr>
 							<td>{{.ID}}</td>
 							<td>
-								<a href="{{$.Link}}/{{.ID}}">{{.Slug}}</a>
+								<a href="{{$.Link}}/{{.Slug}}">{{.Slug}}</a>
 							</td>
 							<td class="gt-ellipsis tw-max-w-48">{{.Description}}</td>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
-							<td></td>
 							<td>
 								<div class="tw-flex tw-gap-2">
-									<a href="{{$.Link}}/{{.ID}}" data-tooltip-content="{{ctx.Locale.Tr "admin.badges.details"}}">{{svg "octicon-star"}}</a>
-									<a href="{{$.Link}}/{{.ID}}/edit" data-tooltip-content="{{ctx.Locale.Tr "edit"}}">{{svg "octicon-pencil"}}</a>
+									<a href="{{$.Link}}/{{.Slug}}" data-tooltip-content="{{ctx.Locale.Tr "admin.badges.details"}}">{{svg "octicon-star"}}</a>
+									<a href="{{$.Link}}/{{.Slug}}/edit" data-tooltip-content="{{ctx.Locale.Tr "edit"}}">{{svg "octicon-pencil"}}</a>
 								</div>
 							</td>
 						</tr>