Django 自定义用户和权限设置

cms_project 项目,自定义用户和相关权限设置

1.重写用户模型

1.1 修改配置文件,覆盖默认的User模型

Django允许你通过修改setting.py文件中的 AUTH_USER_MODEL 设置覆盖默认的User模型,其值引用一个自定义的模型。

AUTH_USER_MODEL = 'myapp.MyUser'

上面的值表示Django应用的名称(必须位于INSTALLLED_APPS中)和你想使用的User模型的名称。

注意:
1.在创建任何迁移或者第一次运行 manager.py migrate 前设置 AUTH_USER_MODEL
设置AUTH_USER_MODEL对你的数据库结构有很大的影响。它改变了一些会使用到的表格,并且会影响到一些外键和多对多关系的构造。在你有表格被创建后更改此设置是不被 makemigrations 支持的,并且会导致你需要手动修改数据库结构,从旧用户表中导出数据,可能重新应用一些迁移。

警告 :
1.确保 AUTH_USER_MODEL 引用的模型在所属app中第一个迁移文件中被创建
由于Django的可交换模型的动态依赖特性的局限,你必须确保 AUTH_USER_MODEL 引用的模型在所属app中第一个迁移文件中被创建(通常命名为 0001_initial),否则你会碰到错误。

1.2 引用User模型

AUTH_USER_MODEL 设置为自定义用户模型时,如果你直接引用User(例如:通过一个外键引用它),你的代码将不能工作。你应该使用django.contrib.auth.get_user_model()来引用用户模型————指定的自定义用户模型或者User

from django.contrib.auth import get_user_model

User = get_user_model()

当你定义一个外键或者到用户模型的多对多关系是,你应该使用AUTH_USER_MODEL设置来指定自定义的模型。

from django.conf import settings
from django.db import models

class Article(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL)

一般来说,在导入时候执行的代码中,你应该使用 AUTH_USER_MODEL 设置引用用户模型。get_user_model() 只在Django已经导入所有的模型后才工作。

1.3 指定自定义的用户模型

1.3.1 Django 期望你自定义的 User model 满足一些最低要求:
  1. 模型必须有一个唯一的字段可被用于识别目的。可以是一个用户名,电子邮件地址,或任何其它独特属性。
  2. 定制一个User Model最简单的方式是构造一个兼容的用户模型继承于AbstractBaseUser
    AbstractBaseUser提供了User类最核心的实现,包括哈希的passwords和 标识的密码重置。
1.3.2 下面为一些AbstractBaseUser的子类必须定义的关键的字段和方法:

USERNAME_FIELD
必须设置。 设置认证标识,设置成标识的字段 unique=True

class MyUser(AbstractBaseUser):
    identifier = models.CharField(max_length=40, unique=True)
    ...
    USERNAME_FIELD = 'identifier'

REQUIRED_FIELDS
必须设置。当通过createsuperuser管理命令创建一个用户时,用于提示的一个字段名称列表。

class MyUser(AbstractBaseUser):
    ...
    date_of_birth = models.DateField()
    height = models.FloatField()
    ...
    REQUIRED_FIELDS = ['date_of_birth', 'height']

列表中不应该包含USERNAME_FIELD字段和password字段。

is_active
必须定义。 一个布尔属性,标识用户是否是 "active" 的。AbstractBaseUser默认为 Ture

get_full_name()
必须定义。 long格式的用户标识。

get_short_name()
必须定义。 short格式的用户标识。

1.3.3 下面为一些AbstractBaseUser的子类可以使用的方法:

get_username()
返回 USERNAME_FIELD 的值。

is_anonymous()
一直返回 False。用来区分 AnonymousUser。

is_authenticated()
一直返回 Ture。用来告诉用户已被认证。

set_password(raw_password)
设置密码。按照给定的原始字符串设置用户的密码,taking care of the password hashing。 不保存 AbstractBaseUser 对象。如果没有给定密码,密码就会被设置成不使用,同用set_unusable_password()。

check_password(raw_password)
检查密码是否正确。 给定的密码正确返回 True。

set_unusable_password()
设置user无密码。 不同于密码为空,如果使用 check_password(),则不会返回True。不保存AbstractBaseUser 对象。

has_usable_password()
如果设置了set_unusable_password(),返回False。

get_session_auth_hash()
返回密码字段的HMAC。 Used for Session invalidation on password change.

1.3.4 为你的User模型自定义一个管理器

如果你的User模型定义了这些字段:username, email, is_staff, is_active, is_superuser, last_login, and date_joined跟默认的User没什么区别, 那么你还不如仅仅替换Django的UserManager就行了; 总之,如果你的User定义了不同的字段, 你就要去自定义一个管理器,它继承自BaseUserManager并提供两个额外的方法:

create_user(username_field, password=None, other_fields)
接受username field和required字段来创建用户。例如,如果使用email作为username field, date_of_birth作为required field:

def create_user(self, email, date_of_birth, password=None):
    # create user here
    ...

create_superuser(username_field, password, other_fields)
接受username field和required字段来创建superuser。例如,如果使用email作为username field, date_of_birth作为required field:

def create_superuser(self, email, date_of_birth, password):
    # create superuser here
    ...

create_superuser中的password是必需的

1.4 扩展Django默认的User

如果你完全满意Django的用户模型和你只是想添加一些额外的属性信息,你只需继承 django.contrib.auth.models.AbstractUser 然后添加自定义的属性。AbstractUser 作为一个抽象模型提供了默认的User的所有的实现(AbstractUser provides the full implementation of the default User as an abstract model.)。

1.5 自定义用户与内置身份验证表单

Django内置的forms和views和相关联的user model有一些先决条件。如果你的user model没有遵循同样的条件,则需要定义一个替代的form,通过form成为身份验证views配置的一部分。

UserCreationForm
依赖于User Model. 扩展User时必须重写。

UserChangeForm
依赖于User Model. 扩展User时必须重写。

AuthenticationForm
Works with any subclass of AbstractBaseUser, and will adapt to use the field defined in USERNAME_FIELD.

PasswordResetForm
Assumes that the user model has a field named email that can be used to identify the user and a boolean field named is_active to prevent password resets for inactive users.

SetPasswordForm
Works with 任何AbstractBaseUser子类

PasswordChangeForm
Works with 任何AbstractBaseUser子类

AdminPasswordChangeForm
Works with 任何AbstractBaseUser子类

1.6 自定义用户和django.contrib.admin

如果你想让你自定义的User模型也可以在站点管理上工作,那么你的模型应该再定义一些额外的属性和方法。 这些方法允许管理员去控制User到管理内容的访问:

is_staff
是否允许user访问admin界面

is_active
用户是否活跃。

has_perm(perm, obj=None):
user是否拥有perm权限。

has_module_perms(app_label):
user是否拥有app中访问models的权限

你同样也需要注册你自定义的用户模型到admin。如果你的自定义用户模型扩展于django.contrib.auth.models.AbscustomauthtractUser,你可以用django的 django.contrib.auth.admin.UserAdmin 类。如果你的用户模型扩展于 AbstractBaseUser,你需要自定义一个ModelAdmin类。他可能继承于默认的django.contrib.auth.admin.UserAdmin。然而,你也需要覆写一些django.contrib.auth.models.AbstractUser 字段的定义不在你自定义用户模型中的。

1.7 自定义用户和权限

如果想让在自定义用户模型中包含Django的权限控制框架变得简单,Django提供了PermissionsMixin。这是一个抽象的类,你可以为你的自定义用户模型中的类的层次结构中包含它。它提供给你所有Django权限类所必须的的方法和字段

1.7.1 如果要定制User的权限系统,最简单的方法是继承PermissionsMixin

源码:

class PermissionsMixin(models.Model):
    """
    A mixin class that adds the fields and methods necessary to support
    Django's Group and Permission model using the ModelBackend.
    """
    is_superuser = models.BooleanField(_('superuser status'), default=False,
        help_text=_('Designates that this user has all permissions without '
                    'explicitly assigning them.'))
    groups = models.ManyToManyField(Group, verbose_name=_('groups'),
        blank=True, help_text=_('The groups this user belongs to. A user will '
                                'get all permissions granted to each of '
                                'their groups.'),
        related_name="user_set", related_query_name="user")
    user_permissions = models.ManyToManyField(Permission,
        verbose_name=_('user permissions'), blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name="user_set", related_query_name="user")

    class Meta:
        abstract = True

    def get_group_permissions(self, obj=None):
        """
        Returns a list of permission strings that this user has through their
        groups. This method queries all available auth backends. If an object
        is passed in, only permissions matching this object are returned.
        """
        permissions = set()
        for backend in auth.get_backends():
            if hasattr(backend, "get_group_permissions"):
                permissions.update(backend.get_group_permissions(self, obj))
        return permissions

    def get_all_permissions(self, obj=None):
        return _user_get_all_permissions(self, obj)

    def has_perm(self, perm, obj=None):
        """
        Returns True if the user has the specified permission. This method
        queries all available auth backends, but returns immediately if any
        backend returns True. Thus, a user who has permission from a single
        auth backend is assumed to have permission in general. If an object is
        provided, permissions for this specific object are checked.
        """

        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        # Otherwise we need to check the backends.
        return _user_has_perm(self, perm, obj)

    def has_perms(self, perm_list, obj=None):
        """
        Returns True if the user has each of the specified permissions. If
        object is passed, it checks if the user has all required perms for this
        object.
        """
        for perm in perm_list:
            if not self.has_perm(perm, obj):
                return False
        return True

    def has_module_perms(self, app_label):
        """
        Returns True if the user has any permissions in the given app label.
        Uses pretty much the same logic as has_perm, above.
        """
        # Active superusers have all permissions.
        if self.is_active and self.is_superuser:
            return True

        return _user_has_module_perms(self, app_label)
1.7.2 Django内置的User对象就继承了AbstractBaseUser和PermissionsMixin:

源码:

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    """
    An abstract base class implementing a fully featured User model with
    admin-compliant permissions.
    Username, password and email are required. Other fields are optional.
    """
    username = models.CharField(_('username'), max_length=30, unique=True,
        help_text=_('Required. 30 characters or fewer. Letters, digits and '
                    '@/./+/-/_ only.'),
        validators=[
            validators.RegexValidator(r'^[\w.@+-]+$',
                                      _('Enter a valid username. '
                                        'This value may contain only letters, numbers '
                                        'and @/./+/-/_ characters.'), 'invalid'),
        ],
        error_messages={
            'unique': _("A user with that username already exists."),
        })
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    is_staff = models.BooleanField(_('staff status'), default=False,
        help_text=_('Designates whether the user can log into this admin '
                    'site.'))
    is_active = models.BooleanField(_('active'), default=True,
        help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.'))
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')
        abstract = True

    def get_full_name(self):
        """
        Returns the first_name plus the last_name, with a space in between.
        """
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        "Returns the short name for the user."
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """
        Sends an email to this User.
        """
        send_mail(subject, message, from_email, [self.email], **kwargs)


class User(AbstractUser):
    """
    Users within the Django authentication system are represented by this
    model.
    Username, password and email are required. Other fields are optional.
    """
    class Meta(AbstractUser.Meta):
        swappable = 'AUTH_USER_MODEL'
1.7.3 PermissionsMixin提供的这些方法和属性:

is_superuser
布尔类型。 Designates that this user has all permissions without explicitly assigning them.

get_group_permissions(obj=None)
Returns a set of permission strings that the user has, through their groups.

If obj is passed in, only returns the group permissions for this specific object.

get_all_permissions(obj=None)
Returns a set of permission strings that the user has, both through group and user permissions.

If obj is passed in, only returns the permissions for this specific object.

has_perm(perm, obj=None)
Returns True if the user has the specified permission, where perm is in the format "<app label>.<permission codename>" (see permissions). If the user is inactive, this method will always return False.

If obj is passed in, this method won’t check for a permission for the model, but for this specific object.

has_perms(perm_list, obj=None)
Returns True if the user has each of the specified permissions, where each perm is in the format "<app label>.<permission codename>". If the user is inactive, this method will always return False.

If obj is passed in, this method won’t check for permissions for the model, but for the specific object.

has_module_perms(package_name)
Returns True if the user has any permissions in the given package (the Django app label). If the user is inactive, this method will always return False.

1.8 完整的代码

customauth/models.py

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser, PermissionsMixin
)
from django.conf import settings


class MyUserManager(BaseUserManager):
    def create_user(self, email, date_of_birth, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
            date_of_birth=date_of_birth,
        )
        user.is_superuser = False
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, date_of_birth, password):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(email,
            password=password,
            date_of_birth=date_of_birth
        )
        user.is_admin = True
        user.is_superuser = True
        user.save(using=self._db)
        return user


class MyUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    user_name = models.CharField(max_length=20, default='')
    uid = models.IntegerField(default=0)
    phone = models.CharField(max_length=20, default='')
    tap = models.CharField(max_length=128, default='')
    token = models.IntegerField(default=0)
    website = models.URLField(blank=True)
    date_of_birth = models.DateField()
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['date_of_birth']

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __str__(self):              # __unicode__ on Python 2
        return self.email
    
    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin
        
    
class UserProfileAdminManger(models.Model):
    myuser = models.ForeignKey(settings.AUTH_USER_MODEL)
    caption = models.CharField(max_length=128)
    
    def __str__(self):
        return self.myuser.email
    
class UserProfileManger(models.Model):
    myuser = models.ForeignKey(settings.AUTH_USER_MODEL)
    caption = models.CharField(max_length=128)
    
    def __str__(self):
        return self.myuser.email

class UserProfileEditor(models.Model):
    myuser = models.ForeignKey(settings.AUTH_USER_MODEL)
    caption = models.CharField(max_length=128)
    
    def __str__(self):
        return self.myuser.email

customauth/admin.py

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from customauth.models import MyUser, UserProfileAdminManger, UserProfileManger, UserProfileEditor



class UserCreationForm(forms.ModelForm):
    """A form for creating new users. Includes all the required
    fields, plus a repeated password."""
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

    class Meta:
        model = MyUser
        fields = ('email', 'password', 'date_of_birth')

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user


class UserChangeForm(forms.ModelForm):
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    password hash display field.
    """
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = MyUser
        fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]


class MyUserAdmin(UserAdmin):
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('email', 'password', 'date_of_birth', 'is_admin')
    list_filter = ('is_admin', 'groups',)
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('date_of_birth',)}),
        ('Permissions', {'fields': ('is_admin', 'groups','user_permissions',)}),
    )
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'date_of_birth', 'password1', 'password2')}
        ),
    )
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ('groups','user_permissions',)

# Now register the new UserAdmin...
admin.site.register(MyUser, MyUserAdmin)
# ... and, since we're not using Django's built-in permissions,

admin.site.register(UserProfileAdminManger)
admin.site.register(UserProfileManger)
admin.site.register(UserProfileEditor)

customauth.py/forms.py

from django import forms
from customauth.models import MyUser, UserProfileAdminManger, UserProfileManger, UserProfileEditor

        
class MyUserForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput())
    class Meta:
        model = MyUser
        fields = ('email', 'date_of_birth', 'user_name', 'phone', 'tap', 'password')


class UserProfileAdminMangerForm(forms.ModelForm):
    caption = forms.CharField(max_length = 128) 
    
    class Meta:
        model = UserProfileAdminManger
        fields = ('caption',)
        
class UserProfileMangerForm(forms.ModelForm):
    caption = forms.CharField(max_length = 128) 
    
    class Meta:
        model = UserProfileManger
        fields = ('caption',)

                
class UserProfileEditorForm(forms.ModelForm):
    caption = forms.CharField(max_length = 128) 
    
    class Meta:
        model = UserProfileEditor
        fields = ('caption',)

customauth/views.py

from django.shortcuts import render
from django.http import HttpResponse
from customauth.forms import MyUserForm, UserProfileAdminMangerForm, UserProfileMangerForm, UserProfileEditorForm
from django.contrib.auth import authenticate, login
from django.http import HttpResponseRedirect, HttpResponse
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout
from django.contrib.auth.models import Group

from django.contrib.auth import get_user_model
User = get_user_model()

def index(request):
    context_dict = {'boldmessage': "There is the users manage!!!"}
    return render(request, 'customauth/index.html', context_dict)


def registeradmin(request):
    registered = False
    if request.method == 'POST':
        myuser_form = MyUserForm(data=request.POST)
        profileadminmanger_form = UserProfileAdminMangerForm(data=request.POST)
        
        if myuser_form.is_valid() and profileadminmanger_form.is_valid():
            user = myuser_form.save()
            user.set_password(user.password)
            user.save()
            print("1111111111111111")
            print(user.groups.add(Group.objects.get(name= 'Admin')))
            #user.groups=Group.objects.get(name= '111')
            print(Group.objects.get(name= 'Admin'))
            print(user.groups.name)
            print("1111111111111111")
   
            profileadminmanger = profileadminmanger_form.save(commit=False)
            profileadminmanger.myuser = user
            profileadminmanger.save()
            registered = True
        else:
            print (myuser_form.errors, profileadminmanger_form.errors)
    else:
        myuser_form = MyUserForm()
        profileadminmanger_form = UserProfileAdminMangerForm()
    return render(request,'customauth/registeradmin.html',
                    {'myuser_form': myuser_form,
                    'profileadminmanger_form': profileadminmanger_form,
                    'registered': registered} )


def registermanger(request):
    registered = False
    if request.method == 'POST':
        myuser_form = MyUserForm(data=request.POST)
        profilemanger_form = UserProfileMangerForm(data=request.POST)
        
        if myuser_form.is_valid() and profilemanger_form.is_valid():
            user = myuser_form.save()
            user.set_password(user.password)
            user.save()
            print("1111111111111111")
            user.groups.add(Group.objects.get(name= 'Manger'))
            print(user.groups)
            print("1111111111111111")
   
            profilemanger = profilemanger_form.save(commit=False)
            profilemanger.myuser = user
            profilemanger.save()
            registered = True
        else:
            print (myuser_form.errors, profilemanger_form.errors)
    else:
        myuser_form = MyUserForm()
        profilemanger_form = UserProfileMangerForm()
    return render(request,'customauth/registermanger.html',
                    {'myuser_form': myuser_form,
                    'profilemanger_form': profilemanger_form,
                    'registered': registered} )

                        
def registereditor(request):
    registered = False
    if request.method == 'POST':
        myuser_form = MyUserForm(data=request.POST)
        profileeditor_form = UserProfileEditorForm(data=request.POST)
        
        if myuser_form.is_valid() and profileeditor_form.is_valid():
            user = myuser_form.save()
            user.set_password(user.password)
            user.save()
            print("1111111111111111")
            print(user.groups.add(Group.objects.get(name= 'Editor')))
            #user.groups=Group.objects.get(name= '111')
            print(user.groups.name)
            print("1111111111111111")
   
            profileeditor = profileeditor_form.save(commit=False)
            profileeditor.myuser = user
            profileeditor.save()
            registered = True
        else:
            print (myuser_form.errors, profileeditor_form.errors)
    else:
        myuser_form = MyUserForm()
        profileeditor_form = UserProfileEditorForm()
    return render(request,'customauth/registereditor.html',
                    {'myuser_form': myuser_form,
                    'profileeditor_form': profileeditor_form,
                    'registered': registered} )

                        
def user_login(request):
    if request.method == 'POST':
        email = request.POST.get('email')
        password = request.POST.get('password')
        user = authenticate(email=email, password=password)
        if user:
            if user.is_active:
                login(request, user)
                return render(request, 'customauth/index.html', {})
            else:
                return HttpResponse("Your Rango account is disabled.")
        else:
            print ("Invalid login details: {0}, {1}".format(username, password))
            return HttpResponse("Invalid login details supplied.")
    else:
        return render(request, 'customauth/login.html', {})


@login_required(login_url='/users/login/')
def restricted(request):
    return HttpResponse("Since you're logged in, you can see this text!")


@login_required
def user_logout(request):
    logout(request)
    return render(request, 'customauth/index.html', {})

customauth/urls.py

from django.conf.urls import patterns, url
from customauth import views

urlpatterns = patterns('',
    url(r'^$', views.index, name='index'),
    url(r'^registeradmin/$', views.registeradmin, name='registeradmin'),
    url(r'^registermanger/$', views.registermanger, name='registermanger'),
    url(r'^registereditor/$', views.registereditor, name='registereditor'),
    url(r'^login/$', views.user_login, name='login'),
    url(r'^restricted/', views.restricted, name='restricted'),
    url(r'^logout/$', views.user_logout, name='logout'),
    #url(r'^homepage/$', views.index, name='index'),


    )

2.更改相关业务的权限设置

完整代码:

blog/models.py

#coding:utf-8
from django.db import models
from django.template.defaultfilters import slugify
import random


class Tag(models.Model):
    name = models.CharField(max_length=128, unique=True)
    likes = models.IntegerField(default=0)
    views = models.IntegerField(default=0)
    slug = models.SlugField(unique=True)
    
    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super(Tag, self).save(*args, **kwargs)
                        
    def __str__(self):
        return self.name
                                               
                                                                                
class Author(models.Model):
    name = models.CharField(max_length=30)
    email = models.EmailField(blank=True)
    website = models.URLField(blank=True)
                                    
    def __str__(self):
        return self.name


class Article(models.Model):
    tag = models.ForeignKey(Tag)
    caption = models.CharField(max_length=128)
    views = models.IntegerField(default=0)
    subcaption = models.CharField(max_length=128)
    publish_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)
    author = models.CharField(max_length=20)
    content = models.TextField()
    slug = models.SlugField(unique=True)
    
    class Meta:
        permissions = (
            ("view_blog", "Can see available Blog"),
            
        )
   
    
    def save(self, *args, **kwargs):
        self.slug = slugify(str(random.randint(100000, 999999)))
        super(Article, self).save(*args, **kwargs)

    def __str__(self):
        return self.caption

blog/forms.py

#coding:utf-8
from django import forms
from blog.models import Tag, Article, Author

class TagForm(forms.ModelForm):
    name = forms.CharField(max_length=128, help_text="Please enter the Tag name.")
    likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
    views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
    slug = forms.CharField(widget=forms.HiddenInput(), required=False)
    
    class Meta:
        model = Tag
        fields = ('name',)
        

class ArticleForm(forms.ModelForm):
    caption = forms.CharField(max_length=128, help_text="Please enter the caption of the Blog.")
    subcaption = forms.CharField(max_length=128, help_text="Please enter the subcaption of the Blog.")
    content = forms.CharField(widget=forms.Textarea, help_text="Please enter the content of the Blog.")
    views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
    slug = forms.CharField(widget=forms.HiddenInput(), required=False)
    
    class Meta:
        model = Article
        exclude = ('tag','author','publish_time', 'update_time',)

blog/admin.py

#coding:utf-8
from django.contrib import admin
from blog.models import Tag, Author, Article

admin.site.register(Article)
admin.site.register(Author)
admin.site.register(Tag)

blog/views.py

#coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse
from blog.models import Article, Tag, Author
from django.template import RequestContext
from blog.forms import TagForm, ArticleForm
from django.http import HttpResponseRedirect
import time
from django.template.defaultfilters import slugify
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.decorators import permission_required, user_passes_test
from guardian.models import UserObjectPermission
from guardian.shortcuts import assign_perm, get_perms
from django.contrib.auth.models import Group, Permission
from django.contrib.auth import get_user_model
User = get_user_model() 

def index(request):
    tag_list = Tag.objects.order_by('-likes')[:10]
    context_dict = {'tags':tag_list}
    article_list = Article.objects.order_by('-publish_time')[:10]
    context_dict['articles'] = article_list
    return render(request, 'blog/index.html', context_dict)

def about(request):
    return HttpResponse("Designed by CDP !!!")


def tag(request, tag_name_slug):
    tag_list = Tag.objects.order_by('-likes')[:10]
    context_dict = {'tags':tag_list}
    try:
        tag = Tag.objects.get(slug=tag_name_slug)
        context_dict['tag_name'] = tag.name
        articles = Article.objects.filter(tag=tag)
        context_dict['article'] = articles.order_by('-publish_time')
        context_dict['tag'] = tag
        context_dict['tag_name_slug']=tag_name_slug
    except Tag.DoesNotExist:
        pass
    return render(request, 'blog/tag.html', context_dict)

def name_check(user):
    return user.username == 'huiyu'


#@permission_required('blog.view_blog', login_url='http://www.zhuiyinggu.com:33333/users/login/')
def article(request, tag_name_slug, article_name_slug):
    context_dict = {}
    try:
        article = Article.objects.get(slug=article_name_slug)
        tag = Tag.objects.get(slug=tag_name_slug)

        context_dict['article'] = article
        context_dict['tag'] = tag
        context_dict['tag_name_slug']=tag_name_slug
        context_dict['article_name_slug']=article_name_slug
    except Tag.DoesNotExist:
        pass
    return render(request, 'blog/article.html', context_dict)

@permission_required('blog.add_tag', login_url='http://www.zhuiyinggu.com:33333/users/login/')
def add_tag(request):
    if request.method == 'POST':
        form = TagForm(request.POST)
        if form.is_valid():
            form.save(commit=True)
            return index(request)
        else:
            print (form.errors)
    else:
        form = TagForm()
    
    return render(request, 'blog/add_tag.html', {'form': form})


@permission_required('blog.add_article', login_url='http://www.zhuiyinggu.com:33333/users/login/')
def add_article(request, tag_name_slug):
    try:
        cat = Tag.objects.get(slug=tag_name_slug)
    except Tag.DoesNotExist:
        cat = None

    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            if cat:  
                article = form.save(commit=False)
                article.tag = cat 
                article.views = 0
                article.save()
                assign_perm('blog.delete_article', request.user, article)
                assign_perm('blog.delete_article', Group.objects.get(name= 'Admin'), article)
                assign_perm('blog.delete_article', Group.objects.get(name= 'Manger'), article)
                return tag(request, tag_name_slug)
            else:
                print (cat)
        else:
            print (form.errors)
    else:
        form = ArticleForm()
        print ('5')

    context_dict = {'form':form, 'tag': cat, 'type':cat.slug}
    return render(request, 'blog/add_article.html', context_dict)



def edit_article(request, tag_name_slug, article_name_slug):
    context_dict = {}
    try:
        cat = Tag.objects.get(slug=tag_name_slug)
    except Tag.DoesNotExist:
        cat = None

    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            if cat:
                article = form.save(commit=False)
                article.tag = cat
                article.views = 0
                article.save()
                return tag(request, tag_name_slug)
        else:
            print (form.errors)
    else:
        form = ArticleForm()
    
        try:
            article = Article.objects.get(slug=article_name_slug)
            context_dict['article'] = article
            context_dict['tag'] = cat
            context_dict['tag_name_slug']=tag_name_slug
            context_dict['article_name_slug']=article_name_slug
    
        except Tag.DoesNotExist:
            pass

        context_dict['form'] = form
        context_dict['type'] = cat.slug
    return render(request, 'blog/edit_article.html', context_dict)
    

def delete_article(request, tag_name_slug, article_name_slug): 
    tag_list = Tag.objects.order_by('-likes')[:10]
    context_dict = {'tags':tag_list}
        
    tag = Tag.objects.get(slug=tag_name_slug)
    context_dict['tag_name'] = tag.name
    articles = Article.objects.filter(tag=tag)
    context_dict['article'] = articles.order_by('-publish_time')
    context_dict['tag'] = tag
    context_dict['tag_name_slug']=tag_name_slug
    
    if request.user.has_perm('delete_article', Article.objects.get(slug=article_name_slug)):
        article = Article.objects.get(slug=article_name_slug)
        article.delete()
    
    return render(request, 'blog/tag.html', context_dict)   

blog/urls.py

from django.conf.urls import patterns, url
from blog import views


urlpatterns = patterns('',
    url(r'^about/$', views.about, name='about'),
    url(r'^$', views.index, name='index'),
    url(r'^tag/(?P<tag_name_slug>[\w\-]+)/$', views.tag, name='tag'),
    url(r'^add_tag/$', views.add_tag, name='add_tag'), 
    url(r'^tag/(?P<tag_name_slug>[\w\-]+)/add_article/$', views.add_article, name='add_article'),
    url(r'^tag/(?P<tag_name_slug>[\w\-]+)/(?P<article_name_slug>[\w\-]+)/$', views.article, name='article'),
    url(r'^tag/(?P<tag_name_slug>[\w\-]+)/(?P<article_name_slug>[\w\-]+)/delete/$', views.delete_article, name='delete_article'),
)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容