SoFunction
Updated on 2024-11-13

Django Admin method to implement foreign key filtering

Description and Model

Environment:

➜ python

Python 3.6.3 |Anaconda custom (x86_64)| (default, Oct 6 2017, 12:04:38)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> print(django.get_version())
2.0.1
>>>

Update 05/23/2018:

The initial parameter can be passed through the get_changeform_initial_data function.

# 
@(Score)
class ScoreConfigAdmin(FilterUserAdmin):
  # fields = ('id','name')
  form = ScoreConfigAdminForm

  def get_changeform_initial_data(self, request):
    initial = super().get_changeform_initial_data(request)
    ({'uid': })
    return initial

# 
class ScoreConfigAdminForm():
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    if not ('initial'):
      return
     = ('initial').get('uid')

  class Meta:
    model = Score
    fields = '__all__'

There is a Blog that supports multiple users (using django admin), and each Post needs to record who published it and to which Blog it belongs.

There are two ways to define the relationship between user and Blog, Blog and Post, one is to use the independent relationship table, and the other is to use the foreign key directly in the Model definition.

The latter model is defined as follows:

from  import User
from  import models

class Blog():
  '''
  Blog
  '''
  id = (unique=True, primary_key = True, verbose_name="Serial number")
  name = (max_length=255, blank=True, null=True, verbose_name="Name")
  user = (User, on_delete=)
  create_time = (verbose_name='Add time', auto_now_add=True, blank=True)

  class Meta:
    verbose_name = 'Blog'
    verbose_name_plural = 'Blog Management'

  def __str__(self):
    return 

class Post():
  '''
  Post content
  '''
  id = (unique=True, primary_key = True, verbose_name="Serial number")
  title = (max_length=255, blank=True, null=True, verbose_name="Title.")
  content = (max_length=1024, blank=True, null=True, verbose_name="Content")
  blog = (Blog, on_delete=, verbose_name="Blog")
  user = (User, on_delete=)
  create_time = (verbose_name='Add time', auto_now_add=True, blank=True)

  class Meta:
    verbose_name = 'Articles'
    verbose_name_plural = 'Article Management'

  def __str__(self):
    return 

Implemented in Admin

There are two places in admin, one is filtering by user in Blog and Post lists, and the other is filtering by current user when adding a new Post. The complete code is as follows:

from  import admin
from django import forms

# Register your models here.
from django_summernote.admin import SummernoteModelAdmin
from .models import Team, Member, Activity, Score



from .models import Blog, Post
class FilterUserAdmin():
  '''
  Filter by user base, class
  '''
  def save_model(self, request, obj, form, change):
    # TODO needs to consider different users making changes to the same data.
     = 
    ()

  def get_queryset(self, request):
    # For Django < 1.6, override queryset instead of get_queryset
    qs = super(FilterUserAdmin, self).get_queryset(request) 
    # Can't add this, adding it will cause superuser to update the data of normal users.
    # if .is_superuser:
    #   return qs
    return (user=)

  def has_change_permission(self, request, obj=None):
    has_class_permission = super(FilterUserAdmin, self).has_change_permission(request, obj)
    if not has_class_permission:
      return False
    if obj is not None and not .is_superuser and  != :
      return False
    return True


class BlogConfigAdmin(FilterUserAdmin):
  list_display = ('id','name', 'create_time')
  exclude = ['user']
  list_per_page = 50

(Blog, BlogConfigAdmin)


class PostConfigAdmin(FilterUserAdmin):
  list_display = ('id','title', 'create_time')
  exclude = ['user']
  list_per_page = 50

  def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
    # When adding a new Post, the associated Blog needs to be filtered, the key is in the following sentence.
    context['adminform'].['blog'].queryset = (user=)
    return super(MemberConfigAdmin, self).render_change_form(request, context, add, change, form_url, obj)


(Post, PostConfigAdmin)

Say two sentences.

Putting a breakpoint in render_change_form and debugging it directly will reveal more interesting things.

Above this Django Admin to achieve foreign key filtering is all I have to share with you, I hope to give you a reference, and I hope you support me more.