I'm working on a project developed in Python 2.7 and Django 1.11.
I'm trying to show in admin page two fields passing through a ManyToMany field.
Here the models:
class ModelZero(Model):
# some fields
mtm_field = models.ManyToManyField(to="ModelOne", through="ModelTwo")
class ModelOne(Model):
# some fields
field_1_1 = models.CharField(unique=True, max_length=200)
field_1_2 = models.BooleanField(default=True)
class ModelTwo(Model):
# some fields
field_2_1 = models.ForeignKey('ModelOne', on_delete=models.CASCADE)
field_2_2 = models.BooleanField(default=True)
In the ModelZero admin page I want to show some fields from the ModelZero itself plus field_2_1 and field_2_2 from ModelTwo.
More in detail, the field_2_1 should be present using a custom widget.
Please note that ModelZeroAdmin is an inline ones.
Here the admin page:
class ModelZeroAdmin(DynamicRawIDMixin, admin.TabularInline):
model = ModelZero
fields = ('some', 'fields', 'field_2_2')
form = forms.ModelZeroForm
def field_2_2(self, obj):
return obj.mtm_field.through.field_2_2
Here the form:
class ModelZeroForm(ModelForm):
class Meta:
widgets = {
"mtm_field.through.field_2_1": dal.autocomplete.ModelSelect2Multiple(
url="my-autocomplete-url"
)
}
In this way i have two errors:
it's not possible add custom fields (field_2_2) in the fields tuple
custom widget is not showed
Is there a way to achieve this goal using this models structure?
I don't have experience with older Django version, but if I am not mistaken the syntax for a related field in admin interface would be something like :mtm_field__field_2_2.
Related
I'm trying to add the employees field to my custom user model in Django REST 2.2. This is how I implemented my custom user (first answer). The employees field is just a list of custom users (so it's related to itself, with a many-to-many relationship).
When I try to add a custom user model from the django interface, it says "this list may not be empty". How can I make it so it can be empty? I thought that's what I added "required=False" for.
users/models.py
class CustomUser(AbstractUser):
employees = models.ManyToManyField("self", related_name='employees')
users/serializers.py (CustomRegisterSerializer is used for registering with rest-auth, CustomUserSerializer is used to view and edit)
class CustomRegisterSerializer(RegisterSerializer):
employees = serializers.RelatedField(many=True, required=False, queryset=CustomUser.objects.all())
def get_cleaned_data(self):
data_dict = super().get_cleaned_data()
data_dict['employees'] = self.validated_data.get('employees', '')
return data_dict
class CustomUserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = ('id', 'email', 'employees')
users/views.py
class CustomUserViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = CustomUserSerializer
I am trying to understand the process of generating generic form views in django. I have a generic view class with just
class BookUpdate(UpdateView):
model = Book
fields = [ 'name',
'pages',
'categorys'
]
which automatically generates a working html form from my model data. But now, I want to modify the field that is shown for categorys, is there any way to do this, or do I have to create a complete working BookForm class and custom BookUpdate class? Here its just 3 fields, but in my real case there are maybe 15 fields that I would need to code by myself, just because of a tiny change in the category field.
Cant I just overwrite the single field, using any class method?
You can either specify fields or form_class in your generic class-based view. With fields, Django will use a modelform_factory to generate the form. There's not much you can customise then.
You should create a BookForm class so that you can customise the fields. In your BookUpdate view, you only need to remove fields and add form_class = BookForm. Here I'm customising the widget for categorys and overriding the form field for pages:
def BookUpdate(UpdateView):
model = Book
form_class = BookForm
def BookForm(ModelForm):
pages = MyCustomPagesField()
class Meta:
model = Book
fields = '__all__'
widgets = {'categorys': MyCustomWidget()}
Note that you don't have to specify all fields, you can use "__all__" to have all fields or you can set exclude = [<list fields to exclude>] to just exclude a couple.
You don't have to code the fields yourself. But there is a small amount of work to do, as there isn't a method to override.
What you need to do is define a custom form. Since that will be a ModelForm, it will use the same logic to automatically create its fields based on the model. You can then override the definition of one of them.
class BookForm(forms.ModelForm):
categorys = forms.ModelMultipleChoiceField(custom_attributes_here...)
class Meta:
model = Book
fields = ["name", "pages", "categorys"]
And now tell your view to use that form:
class BookUpdate(UpdateView):
form_class = BookForm
I have an using the Django admin interface to manage a lot of objects, and one of the page is giving me issue, this page has a field to a related object (Foreign Key) that has a __str__ that also goes to its related objects, this make a lot of queries and is barely useable (Around 3000 queries to show the page as there are a LOT of objects).
I would like to know if there is a way to set a custom queryset ? I would like to add a select_related or prefetch_related to this element.
The part causing issue is this certificate requests list :
The page model (Certificate has the following attribute:
class Certificate(models.Model):
certificate_request = models.OneToOneField(
"CertificateRequest",
verbose_name=_("Certificate request"),
related_name="certificate",
blank=True,
null=True
)
And the related model has this :
class CertificateRequest(models.Model):
domain = models.ForeignKey(
"Domain",
verbose_name=_("Domain"),
related_name="certificate_requests"
)
def __str__(self):
return "{state} certificate request for {domain} from {creation_date}".format(
state=dict(self.STATUS).get(self.status),
domain=self.domain.fqdn,
creation_date=self.creation_date
)
What would be the way to fix this ? How can I set a queryset on this part ?
EDIT: I added more informations.
I tried using a custom form, but this didn't do any change :
class CertificateForm(forms.ModelForm):
certificate_request = forms.ModelChoiceField(queryset=CertificateRequest.objects.select_related("domain"))
class Meta:
model = Certificate
fields = "__all__"
#admin.register(Certificate)
class CertificateAdmin(CompareVersionAdmin):
model = Certificate
class Meta:
form = CertificateForm
You can create a custom ModelForm for your admin where you specify a ModelChoiceField for the ForeignKey. Here you can specify the queryset parameter:
# forms.py
class MyForm(forms.ModelForm):
certificate_request = forms.ModelChoiceField(queryset=CertReq.objects.foo().bar())
# select/prefetch-------^^^^^^^^^^^
class Meta:
model = Foo
# admin.py
class YourAdmin(ModelAdmin):
form = MyForm
The get_object method on the ModelAdmin class is what is responsible for retrieving the object to edit. You could certainly extend that method in your subclass to use select_related as necessary.
The Django admin panel has a search autocomplete with search_fields on the list of objects of a model, but right now I have 3000 users. To add a user manually is dificult with the selectbox; I need the same behavior like the searchfields for selecting a user foreinkey User.
How can I include the Django search feature on the form for editing inside the admin panel?
from myapp.models import Red
from django.contrib.auth.models import User
class Red(models.Model):
customer = models.ForeignKey(User, verbose_name="Cliente")
pub_date = models.DateTimeField(default=datetime.now, blank=True)
Since Django 2.0, you can use autocomplete_fields to generate autocomplete fields for foreign keys.
class UserAdmin(admin.ModelAdmin):
search_fields = ['username', 'email']
class RedAdmin(admin.ModelAdmin):
autocomplete_fields = ['customer']
Django has no built-in autocomplete functionality for foreign keys on admin but the raw_id_fields option may help:
class RedAdmin(admin.ModelAdmin):
raw_id_fields = ("customer", )
If you want real autocomplete then you have to use 3rd-party app like django-autocomplete-light or some of the other solutions.
Is there any way to use a Form Wizard in Admin interface for add/edit Models.
(using Django 1.5.2)
for example:
--models.py--
class AModel(models.Model):
fieldA = models.CharField(max_length=64)
fieldB = models.CharField(max_length=64)
--admin.py--
class Form1(ModelForm):
class Meta:
model = AModel
fields = ('fieldA',)
class Form2( ModelForm ):
class Meta:
model = AModel
fields = ('fieldB',)
.... something add for make this two forms in one multipage admin form , is that possible? or any other way to do the same job.
Thanks in advance.
It isn't possible by using admin module. The only way is either some external plugins or you need to create custom admin views. Google around..