2016-10-25 1 views
0

동일한 모델의 인라인이 2 개 있습니다.관리자 인라인 이름을 얻는 방법 또는 인라인을 변경하는 방법을 정의하는 방법은 무엇입니까?

class UsersInlineAdmin(GenericTabularInline): 
    model = CTSportsToCriterias 

class TeamsInlineAdmin(GenericTabularInline): 
    model = CTSportsToCriterias 

class CTSportsToCriterias(models.Model): 
    user_use = models.BooleanField(verbose_name=_('is available to users?'), default=False) 
    team_use = models.BooleanField(verbose_name=_('is available to teams?'), default=False) 

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) 
    object_id = models.PositiveIntegerField() 
    content_object = GenericForeignKey() 

    criteria_group = models.ForeignKey(CriteriaGroups, verbose_name=_('criteria group')) 

나는 UsersInlineAdmin (이 경우에 user_use이 True)에서 항목을 제거하고이 항목도 (team_use는도 마찬가지입니다) TeamsInlineAdmin에있는 경우, 장고는 자동으로 TeamsInlineAdmin 인라인에서이 항목을 제거 할 때에 따라 때문에 Django 문서, 코드 :

def save_formset(self, request, form, formset, change): 
    for obj in formset.deleted_objects: 
    ... 

은 모델의 개체를 제공합니다.

if (inline_name == 'UsersInlineAdmin' and not obj.team_use) or \ 
    (inline_name == 'TeamsInlineAdmin' and not obj.user_use): 
    obj.delete() 

: 내 경우 모델이 몇 가지 옵션 (team_use \ user_use)를 가질 수 있기 때문에

그래서, 그것은 가능하다 그런 짓을하기 위해 save_formset에서 inline 이름을 얻으려면?

편집 : 나는 form를 추가하고 나는 경우에 user 항목을 추가 할 때 team의 항목이 이미 존재하는 경우, clean()를 오버라이드 (override)하는 경우는, 장고 True로 DB user_use에 업데이트하지 않습니다 . 대신 Django는 새로운 레코드를 만듭니다.

# admin 
class UsersInlineAdmin(GenericTabularInline): 
    model = CTSportsToCriterias 
    form = UserFieldForm 

# form 
class UserFieldForm(forms.ModelForm): 
    class Meta: 
     model = CTSportsToCriterias 

    def clean(self): 
     m = super(UserFieldForm, self).clean() 

     # This trick works ok in case when I want to DELETE user's item, 
     # so the trick changes in DB 'user_use' to False, if 'team_use' already exists 
     if m['DELETE'] is True: 
      try: 
       qs = CTSportsToCriterias.objects.get(object_id=object_id, 
                content_type=content_type, 
                criteria_group=criteria_group, 
                team_use=True) 
       m['id'] = qs.pk 
       m['DELETE'] = m['user_use'] = False 

      except ObjectDoesNotExist: 
       pass 

     # Can not repeate the same trick as above. 
     # When 'team_use' already exists, I want to change the value 'user_use' of this team's obj to True, 
     # but the trick as above does not work in this case - Django adds a new row to DB, instead of update 
     # the existing one. 
     elif m['DELETE'] is False: 
      try: 
       qs = CTSportsToCriterias.objects.get(object_id=object_id, 
                 content_type=content_type, 
                 criteria_group=criteria_group, 
                 team_use=True) 
       m['id'] = qs.pk 
       m['DELETE'] = m['user_use'] = False 

      except ObjectDoesNotExist: 
       pass 

     return m 
+1

당신은이 양식 수준에서 할 수 있습니까? 예를 들어,'clean()'메소드의 체크를 수행하는'UsersInlineAdmin'과'TeamsInlineAdmin'을위한 폼을 만드십시오. 또는 나는 무엇인가 놓치고 있냐? – makaveli

+0

@makaveli,'Form = UserFieldForm'을'UsersInlineAdmin'에 추가하고'UserFieldForm (forms.ModelForm) 클래스를 작성 하시겠습니까 : class Meta : ... def clean (self) : ... do something .. super (...). clean()'? 나는 이것을 시도하고 clean()이 호출되지 않는다. – TitanFighter

+0

예, 모든 것을 올바르게 수행하면 호출됩니다. :) 나는 오늘 똑같은 것을 썼다. 그리고 그것은 잘 동작한다. 어리석은 질문을하지만, 일단 save 명령을 내리면'clean()'메쏘드가 호출된다는 것을 알고 있습니까? 로드시 호출되지 않습니다. 그러나 15-20 분 후에 나는 당신에게 실제적인 예를 드릴 수 있습니다. – makaveli

답변

1
# forms 
class UserFieldForm(forms.ModelForm): 
    user_use = forms.BooleanField(widget=forms.HiddenInput(), initial=True, required=True) 

    def clean(self): 
     m = super(UserFieldForm, self).clean() 

     if m['DELETE'] is True: 
      m['user_use'] = False 

     return m 

class TeamFieldForm(forms.ModelForm): 
    team_use = forms.BooleanField(widget=forms.HiddenInput(), initial=True, required=True) 

    def clean(self): 
     m = super(TeamFieldForm, self).clean() 

     if m['DELETE'] is True: 
      m['team_use'] = False 

     return m 


# admin 
class UsersInlineAdmin(GenericTabularInline): 
    model = CTSportsToCriterias 
    form = UserFieldForm 

class TeamsInlineAdmin(GenericTabularInline): 
    model = CTSportsToCriterias 
    form = TeamFieldForm 


class CriteriaGroupsAdmin(admin.ModelAdmin): 
    inlines = [CriteriaTranslationsInlineAdmin, UsersInlineAdmin, TeamFieldForm] 

    def save_formset(self, request, form, formset, change): 
     instances = formset.save(commit=False) 

     for obj in formset.deleted_objects: 
      if isinstance(instance, CTSportsToCriterias): 
       is_user_use_form = obj.user_use 
       is_team_use_form = obj.team_use 

       # There is just one option in DB (user_use or team_use), so delete obj from DB 
       if not is_user_use_form and not is_team_use_form: 
        obj.delete() 

       else: 
        user_n_team = CTSportsToCriterias.objects.get(
         object_id=obj.object_id, content_type=obj.content_type, criteria_group=obj.criteria_group) 

        # Means 'user_use' exists and we need to change 'team_use' to False 
        if is_user_use_form: 
         user_n_team.team_use = False 

        # Means 'team_use' exists and we need to change 'user_use' to False 
        elif is_team_use_form: 
         user_n_team.user_use = False 

        user_n_team.save() 

     # Saves user_use + team_use in one row as there is no need to use 2 DB rows for each case (user\team) 
     # if user_use or team_use already exists in DB, or just creates a new row. 
     for instance in instances: 
      if isinstance(instance, CTSportsToCriterias): 
       content_type = ContentType.objects.get(id=instance.content_type_id) 
       criteria_group = CriteriaGroups.objects.get(id=instance.criteria_group_id) 

       qs_kwargs = dict(content_type=content_type, object_id=instance.object_id, criteria_group=criteria_group) 

       is_user_use = instance.user_use 
       is_team_use = instance.team_use 

       if is_user_use: 
        qs_kwargs.update(defaults=dict(user_use=is_user_use)) 
       if is_team_use: 
        qs_kwargs.update(defaults=dict(team_use=is_team_use)) 

       CTSportsToCriterias.objects.update_or_create(**qs_kwargs) 
관련 문제