سؤال

ولدي الإعداد مشرف التالية حتى أتمكن من إضافة / تعديل مستخدم وملفهم الشخصي في نفس الوقت.

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    list_display = ['edit_obj', 'name', 'username', 'email', 'is_active',
        'last_login', 'delete_obj']
    list_display_links = ['username']
    list_filter = ['is_active']
    fieldsets = (
        (None, {
            'fields': ('first_name', 'last_name', 'email', 'username',
                'is_active', 'is_superuser')}),
        )
    ordering = ['last_name', 'first_name']
    search_fields = ['first_name', 'last_name']

admin.site.register(User, UserProfileAdmin)

والمشكلة هي أنني بحاجة اثنين من الحقول في النموذج الملف مضمنة أن تكون مطلوبة عند إضافة المستخدم. لا تتحقق شكل مضمنة ما لم يتم إدخال المدخلات. هناك على أية حال لجعل المضمنة المطلوبة، بحيث لا يمكن تركه فارغا؟

هل كانت مفيدة؟

المحلول

وأخذت المشورة كارل وجعل تنفيذ أفضل بكثير ثم واحد الإختراق العش ذكرت في تعليقي إلى إجابته. وإنني هنا الحل:

من وجهة نظري forms.py:

from django.forms.models import BaseInlineFormSet


class RequiredInlineFormSet(BaseInlineFormSet):
    """
    Generates an inline formset that is required
    """

    def _construct_form(self, i, **kwargs):
        """
        Override the method to change the form attribute empty_permitted
        """
        form = super(RequiredInlineFormSet, self)._construct_form(i, **kwargs)
        form.empty_permitted = False
        return form

وعلى admin.py

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile
    extra = 1
    max_num = 1
    formset = RequiredInlineFormSet


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    list_display = ['edit_obj', 'name', 'username', 'email', 'is_active',
        'last_login', 'delete_obj']
    list_display_links = ['username']
    list_filter = ['is_active']
    fieldsets = (
        (None, {
            'fields': ('first_name', 'last_name', 'email', 'username',
                'is_active', 'is_superuser')}),
        (('Groups'), {'fields': ('groups', )}),
    )
    ordering = ['last_name', 'first_name']
    search_fields = ['first_name', 'last_name']


admin.site.register(User, UserProfileAdmin)

وهذا لا بالضبط ما أريد، فهو يجعل التحقق من صحة الملف مضمنة formset. ذلك لأن هناك مطلوبة الحقول في نموذج ملف التعريف أنه سيتم التحقق من صحة وتفشل إذا لم يتم إدخال المعلومات المطلوبة على النموذج المضمنة.

نصائح أخرى

والآن مع جانغو 1.7 يمكنك استخدام min_num المعلمة. لا تحتاج الطبقة RequiredInlineFormSet بعد الآن.

https://docs.djangoproject.com /en/1.8/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.min_num

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile
    extra = 1
    max_num = 1
    min_num = 1 # new in Django 1.7


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    ...


admin.site.register(User, UserProfileAdmin)

وربما يمكنك أن تفعل ذلك، ولكن سيكون لديك للحصول على أيديكم القذرة في قانون formset / المضمنة.

وأولا وقبل كل شيء، أعتقد أنك تريد أن يكون هناك دائما واحدة النموذج في formset في هذه الحالة، وأبدا أكثر من واحد، لذلك عليك أن ترغب في تعيين <لأ href = "HTTP: //docs.djangoproject. كوم / EN / ديف / المرجع / contrib / المشرف / # ماكس-الأسطوانات "يختلط =" noreferrer "> MAX_NUM = 1 و <لأ href =" http://docs.djangoproject.com/en/dev/ المرجع / contrib / المشرف / # اضافية "يختلط =" noreferrer "> اضافية = 1 في ProfileInline الخاص بك.

والمشكلة الأساسية هي أن لديك BaseFormSet._construct_form يمر empty_permitted = صحيح أن كل شكل من أشكال "إضافية" (أي فارغا) في formset. تقول هذه المعلمة النموذج لتجاوز التحقق من صحة إذا دون تغيير. كل ما تحتاجه لايجاد وسيلة لوضع empty_permitted = خطأ للنموذج.

يمكنك استخدام بنفسك BaseInlineFormset فرعية في حياتك مضمنة، بحيث يمكن أن يساعد. يلاحظ أن _construct_form يأخذ ** kwargs ويسمح ذلك لتجاوز kwargs تمريرها إلى الحالات الفردية نموذج، يمكن أن تتجاوز _construct_forms في فئة فرعية Formset الخاص بك، وأنها تمر empty_permitted = خطأ في كل مكالمة ل_construct_form. الجانب السلبي هناك هو أن كنت تعتمد على واجهات برمجة التطبيقات الداخلية (وكنت قد لإعادة كتابة _construct_forms).

وبدلا من ذلك، قد تتمكن من محاولة تجاوز الأسلوب get_formset على ProfileInline الخاص بك، وبعد استدعاء get_formset الوالدين، كزة يدويا في شكل داخل formset عاد:

def get_formset(self, request, obj=None, **kwargs):
    formset = super(ProfileInline, self).get_formset(request, obj, **kwargs)
    formset.forms[0].empty_permitted = False
    return formset

وحول اللعب ونرى ما يمكنك ان تجعل العمل!

والطريقة الأسهل والأكثر طبيعية لذلك هي عبر clean() fomset:

class RequireOneFormSet(forms.models.BaseInlineFormSet):
    def clean(self):
        super().clean()
        if not self.is_valid():
            return
        if not self.forms or not self.forms[0].cleaned_data:
            raise ValidationError('At least one {} required'
                                  .format(self.model._meta.verbose_name))

class ProfileInline(admin.StackedInline):
    model = Profile
    formset =  RequireOneFormSet

و(مستوحاة من rel="nofollow هذا ماثيو فلاناغان المتكررة و تعليق ميتار أدناه، واختبارها للعمل في جانغو 1.11 و 2.0).

وتحتاج إلى تعيين على min_num في مضمنة و validate_min في formset.

https://docs.djangoproject.com/ EN / 1.8 / المواضيع / أشكال / formsets / # التحقق من صحة مين

class SomeInline(admin.TabularInline):
    ...
    min_num = 1

    def get_formset(self, request, obj=None, **kwargs):
        formset = super().get_formset(request, obj=None, **kwargs)
        formset.validate_min = True
        return formset
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top