एक कस्टम उपयोगकर्ता मॉडल के लिए Django के उपयोगकर्ता UserAdmin का उपयोग करना


82

से Django.Contrib.Auth डॉक्स :

Django के डिफ़ॉल्ट उपयोगकर्ता का विस्तार करना यदि आप Django के उपयोगकर्ता मॉडल से पूरी तरह से खुश हैं और आप केवल कुछ अतिरिक्त प्रोफ़ाइल जानकारी जोड़ना चाहते हैं, तो आप बस उप-वर्ग django.contrib.auth.models.AbstractUserजोड़ सकते हैं और अपने कस्टम प्रोफ़ाइल फ़ील्ड जोड़ सकते हैं। यह वर्ग अमूर्त मॉडल के रूप में डिफ़ॉल्ट उपयोगकर्ता का पूर्ण कार्यान्वयन प्रदान करता है।

कहा और किया। मैंने नीचे एक नया मॉडल बनाया:

class MyUser(AbstractUser):
  some_extra_data = models.CharField(max_length=100, blank=True)

यह लगभग Django के मानक की तरह व्यवस्थापक में दिखाता है User। हालाँकि, व्यवस्थापक में सबसे महत्वपूर्ण अंतर यह है कि पासवर्ड- (पुनः) सेट फ़ील्ड मौजूद नहीं है, लेकिन इसके बजाय एक सामान्य CharField प्रदर्शित किया जाता है। क्या मुझे वास्तव में यह काम करने के लिए व्यवस्थापक-विन्यास में सामान को ओवरराइड करना है? यदि हां, तो मैं इसे किसी भी तरह से कैसे कर सकता हूं (अर्थात Django स्रोत से सामान की नकल किए बिना ... eww ...)?

जवाबों:


135

कुछ समय के लिए Django स्रोत कोड के आसपास खुदाई करने के बाद, मुझे एक काम करने वाली आत्मा मिली। मैं इस समाधान से पूरी तरह से खुश नहीं हूं, लेकिन यह काम करने लगता है। बेहतर समाधान सुझाने के लिए स्वतंत्र महसूस करें!


Django मॉडल के UserAdminलिए अच्छा व्यवस्थापक रूप देने के लिए उपयोग करता है User। हमारे admin.py-फाइल में बस इसी का उपयोग करके , हम अपने मॉडल के लिए समान रूप पा सकते हैं।

from django.contrib.auth.admin import UserAdmin
admin.site.register(MyUser, UserAdmin)

हालाँकि, यह अकेला एक अच्छा समाधान नहीं है, क्योंकि Django एडमिन आपके किसी भी विशेष क्षेत्र को प्रदर्शित नहीं करेगा। इसके दो कारण हैं:

  • UserAdminUserChangeFormऑब्जेक्ट को संशोधित करते समय उपयोग किए जाने वाले फॉर्म के रूप में उपयोग करता है , जो इसके बदले Userमें इसके मॉडल के रूप में उपयोग करता है ।
  • UserAdminएक formsets-property को परिभाषित करता है , बाद में उपयोग किया जाता है UserChangeForm, जिसमें आपके विशेष क्षेत्र शामिल नहीं होते हैं।

इसलिए, मैंने एक विशेष परिवर्तन-प्रपत्र बनाया, जो मेटा इनर-क्लास को अधिभारित करता है ताकि परिवर्तन रूप सही मॉडल का उपयोग करे। मुझे UserAdminअपने विशेष क्षेत्रों को फ़ील्डसेट में जोड़ने के लिए भी ओवरलोड करना पड़ा , जो इस समाधान का एक हिस्सा है जो मुझे थोड़ा नापसंद है, क्योंकि यह थोड़ा बदसूरत दिखता है। सुधार का सुझाव देने के लिए स्वतंत्र महसूस करें!

from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm

class MyUserChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = MyUser

class MyUserAdmin(UserAdmin):
    form = MyUserChangeForm

    fieldsets = UserAdmin.fieldsets + (
            (None, {'fields': ('some_extra_data',)}),
    )


admin.site.register(MyUser, MyUserAdmin)

महान! ठीक यही मैं देख रहा था, मैं अपने कस्टम उपयोगकर्ता मॉडल के साथ ऐसा ही कर रहा हूं, AbstractUser का उपयोग कर रहा हूं। यह समाधान बहुत अच्छा काम करता है, कुछ अनुकूलन (फ़ील्ड छिपाते हुए, 'व्यक्तिगत जानकारी' में अपने 'some_extra_data' को जोड़ना) भी अच्छा होगा लेकिन अब के लिए आपने मेरा दिन बना दिया है। धन्यवाद @ निको
Dachmt

डी उपयोगकर्ता के ओवरलोडिंग बदली मैदान? यह काम करता हैं। धन्यवाद।
एच.टी.एम.एल. टैगों

6
यह भी ध्यान दें कि आपको @ kdh454 द्वारा उत्तर के अनुसार उपयोगकर्ता निर्माण फ़ॉर्म को ओवरराइड करने की आवश्यकता है।
ठाणे ब्रिमहल

यह सही है, यह बिल्कुल गड़बड़ नहीं है। Django प्रलेखन इस लेख को इंगित करता है: docs.djangoproject.com/en/2.0/topics/auth/customizing/… ... लेकिन मैं इसके साथ काम करने में सक्षम नहीं था, यह कुछ उपयोगकर्ता विदेशी बाधाओं के बारे में शिकायत कर रहा था। केवल मेरी परियोजना से संबंधित हो सकता है, फिर भी आपका समाधान काम करता है!
व्लादिमीर मार्टन

57

निको का जवाब बेहद मददगार रहा है, लेकिन मैंने पाया कि नया उपयोगकर्ता बनाते समय Django अभी भी उपयोगकर्ता मॉडल का संदर्भ देता है।

टिकट # 19353 इस समस्या का संदर्भ देता है।

इसे ठीक करने के लिए मुझे कुछ और अतिरिक्त करने थे admin.py

admin.py:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from main.models import MyUser
from django import forms


class MyUserChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = MyUser


class MyUserCreationForm(UserCreationForm):
    class Meta(UserCreationForm.Meta):
        model = MyUser

    def clean_username(self):
        username = self.cleaned_data['username']
        try:
            MyUser.objects.get(username=username)
        except MyUser.DoesNotExist:
            return username
        raise forms.ValidationError(self.error_messages['duplicate_username'])


class MyUserAdmin(UserAdmin):
    form = MyUserChangeForm
    add_form = MyUserCreationForm
    fieldsets = UserAdmin.fieldsets + (
        (None, {'fields': ('extra_field1', 'extra_field2',)}),
    )

admin.site.register(MyUser, MyUserAdmin)

आपके समाधान ने मेरे लिए निर्दोष रूप से काम किया। आपका बहुत बहुत धन्यवाद!
गिनीज

3
ध्यान दें कि 1.6 में शुरू, कॉल forms.ValidationErrorमें एक दूसरा तर्क है code='duplicate_username': github.com/django/django/blob/1.6/django/contrib/auth/… इसके अलावा, मैंने 1.6.5 पर यह कोशिश की और, किसी कारण के लिए, मैंने UserChangeFormसभी को ओवरराइड करने की आवश्यकता नहीं थी और परिवर्तन रूप ने मेरे कस्टम फ़ील्ड के साथ ठीक काम किया। मैं क्यों नहीं समझा सकता। ऐसा लगता है कि UserChangeFormकक्षा में model = Userउपस्थित होने के कारण इसे काम नहीं करना चाहिए था: github.com/django/django/blob/1.6.5/django/contrib/auth/…
Nick

2
FYI करें टिकट # 19353 अब तय किया गया है जिसका अनिवार्य रूप से मतलब है कि आपका समाधान बेमानी हो सकता है। अगर हम सिर्फ @ nip3o के समाधान का उपयोग करते हैं तो हमें अच्छा होना चाहिए।
kstratis

50

एक सरल समाधान, admin.py:

from django.contrib.auth.admin import UserAdmin
from main.models import MyUser

class MyUserAdmin(UserAdmin):
    model = MyUser

    fieldsets = UserAdmin.fieldsets + (
            (None, {'fields': ('some_extra_data',)}),
    )

admin.site.register(MyUser, MyUserAdmin)

Django निर्माण और संशोधन के लिए MyUser मॉडल को सही ढंग से संदर्भित करेगा। मैं Django 1.6.2 का उपयोग कर रहा हूं।


मुझे पता नहीं क्यों लेकिन मुझे यह कोशिश करते समय +: 'noneType' और 'tuple' "के लिए" TypeError: असमर्थित ऑपरेंड प्रकार (ओं) मिलते रहे।
चेस रॉबर्ट्स

मैं आपको सुझाव देता हूं कि आप UserAdmin.fieldsets का निरीक्षण करें और देखें कि क्या यह कोई नहीं है
Rômulo Collopy

1
यह सबसे अद्यतन उत्तर है और स्वीकार किया जाना चाहिए
शानदार

1
इसके बजाय None, आप एक स्ट्रिंग इनपुट कर सकते हैं और इसका उपयोग एडमिन फॉर्म में सेक्शन के शीर्षक के रूप में किया जाएगा
गिलाउम लेब्रेटन

@Brillout से सहमत, यह सबसे अच्छा जवाब है। जोड़ने के लिए, आपको यह त्रुटि मिल सकती है, जो समझ में आता है (पायथन 3.8, Django 3):ERRORS: <class 'users.admin.CustomerUserAdmin'>: (admin.E005) Both 'fieldsets' and 'fields' are specified.
निकोरेलियस

9

जब मैंने निर्माण प्रपत्र में एक कस्टम फ़ील्ड जोड़ने का प्रयास किया तो cesc का उत्तर मेरे लिए काम नहीं कर रहा था। शायद यह 1.6.2 से बदल गया है? किसी भी तरह से, मैंने फ़ील्ड को दोनों फ़ील्ड्स में जोड़ते हुए पाया और add_fieldsets ने चाल चली।

ADDITIONAL_USER_FIELDS = (
    (None, {'fields': ('some_additional_field',)}),
)

class MyUserAdmin(UserAdmin):
    model = MyUser

    add_fieldsets = UserAdmin.add_fieldsets + ADDITIONAL_USER_FIELDS
    fieldsets = UserAdmin.fieldsets + ADDITIONAL_USER_FIELDS

admin.site.register(MyUser, MyUserAdmin)

2

एक और समान समाधान ( यहाँ से लिया गया है ):

from __future__ import unicode_literals

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _

from .models import User


class UserAdminWithExtraFields(UserAdmin):

    def __init__(self, *args, **kwargs):
        super(UserAdminWithExtraFields, self).__init__(*args, **kwargs)

        abstract_fields = [field.name for field in AbstractUser._meta.fields]
        user_fields = [field.name for field in self.model._meta.fields]

        self.fieldsets += (
            (_('Extra fields'), {
                'fields': [
                    f for f in user_fields if (
                        f not in abstract_fields and
                        f != self.model._meta.pk.name
                    )
                ],
            }),
        )


admin.site.register(User, UserAdminWithExtraFields)

-1

बस इस प्रकार है

from django.contrib import admin
from .models import MyUser

admin.site.register(MyUser, admin.ModelAdmin)

बस। सभी MyUser मॉडल के फ़ील्ड दिखाए जाएंगे। दिखाने के लिए UserAdmin की फ़ील्ड सूची हार्डकोडेड है (इसका स्रोत कोड देखें), लेकिन ModelAdmin नहीं है। यह लचीला है।


सिफारिश नहीं की गई। यह डिफ़ॉल्ट का उपयोग करेगा ModelAdmin, न कि अनुकूलित का UserAdmin। नतीजा गड़बड़ है।
ddd
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.