Django admin - Use inlines in django admin saving data in current model - python

I need use inlines in django admin for show relation between two models but in the moment that i do, i had to do the reverse relationship to show inlines.
Example:
class OtherModel(models.Model):
field1=models...
........
class Model(models.Model)
field1 = models....
other_model = models.ForeignKey(OtherModel)
I create the inline...
class OtherModelInline(admin.StackedInline):
model = OtherModel
extra = 1
#admin.register(Model):
class ModelAdmin(admin.modelAdmin):
inlines = [OtherModelInline]
So...
When I create the Inline it required foreign key on OtherModel..
How can I show this without change the relationship?

This is the right way to do it.
If you want to use inlines, you need to specify that these two models are somewhat related.

Related

adjust forms that are generated by django generic editing views

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

Python/Django - Generating forms for models.

I have two questions concerning models and forms.
1) What is the best way to create automatically forms for the models?
In the example below I have two models - ModelA and ModelB. I need forms for them - ModelAForm and ModelBForm. They should be defined automatically. I do not want to do it manually, because in the future I will add other models, and all the forms will look the same. I am thinking about creating special decorator for models and use modelform_factory.
from django.db import models
from django.forms import ModelForm
class ModelA(models.Model):
...
class ModelB(models.Model):
...
class ModelAForm(ModelForm):
class Meta:
abstract = ModelA
class ModelBForm(ModelForm):
class Meta:
abstract = ModelB
2) Assuming I am using only ModelForm forms, it is possible to find the form for the model? Example. I have two models ModelA and ModelB, and two forms ModelAForm and ModelBForm. I have instance of ModelA and I would like to identify proper form for this model which I will pass to template - in this case ModelAForm.
Django provides some generic editing views. You only have to provide a model and the view will generate the form automatically. If you want to use the forms to create or update instances you can just use them.
If your really need to create the forms yourself you can use the modelform_factory that these views use themself to create the correct form for your model. But i would first go with the generic views as long as they can be modified to suit your needs.
Just pass it your model and optionally the fields you want. If you omit the fields, all fields will be generated:
from .models import MyModel
from django.forms.models import modelform_factory
my_form = modelform_factory(MyModel, fields=['name', 'age', 'job'])
There's ModelForm in django.
Here's fragment of documentation and link for it.
https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter']
You're probably looking for generic class-based views, where you only pass form_class and model instances, everything else django handles without your help.
Link for them - https://docs.djangoproject.com/en/1.10/ref/class-based-views/

Create editable set of model objects in django admin

I'm trying to create editable set of objects.
I have Visitor model, which can contain set of models Sibling. But the set may be blank. This set should be editable in Django admin, and, I would like it will be generated by built-in tools.
Here is my approach to do this:
class Sibling(models.Model):
VisitorID = models.ForeignKey('Visitor')
# ... some fields
class Visitor(models.Model):
# ... some fields
Siblings = models.ManyToManyField(Sibling, blank=True)
It is bad way because there are all Siblings from all Visitors in the auto-generated form in django admin, but I want only those which are related to specific Visitor.
Could anyone help me or give advice?
One way achieve this with a Serializer class
class Sibling(models.Model):
VisitorID = models.ForeignKey('Visitor')
# ... some fields
class Visitor(models.Model):
# ... some fields
class VisitorSerializer(serializers.ModelSerializer):
sibling = serializers.RelatedField(source='sibling')
class Meta:
model = Visitor
# List all fields in Visitor plus sibling
fields = ('id', 'somefieldinvisitormodel', 'sibling')
The serializer class allows you to override what's being displayed in admin without having to mess with your models. This also allows you to remove the extra relationship you added within visitor.
This isn't an entirely automated solution, but it's close.

Django inlines for manyToMany field

I have a Profile model that has OneToOne relationship with User model.
I also have a Group model that has users field as ManyToMany to User.
I am trying to achieve a simple thing in Django Admin: being able to create a group with some new users and allowing to fill out some of the profile fields for those new users.
I tried a couple of things
class ProfileInline(admin.StackedInline):
model = Profile
class UserInline(admin.StackedInline):
model = Group.users.through
inlines = [ ProfileInline ]
class GroupAdmin(admin.ModelAdmin):
inlines = [
UserInline,
]
exclude = ('users',)
This is not working for me. I only see dropdown fields for user in my group admin and if I try to add a user the form does not have any profile fields.
You can't do that. Django admin inlines are only available if model has foreign key to other model. For you setup you have to find other solution related to your models relation.

Displaying ForeignKey data in Django admin change/add page

I'm trying to get an attribute of a model to show up in the Django admin change/add page of another model. Here are my models:
class Download(model.Model):
task = models.ForeignKey('Task')
class Task(model.Model):
added_at = models.DateTimeField(...)
Can't switch the foreignkey around, so I can't use Inlines, and of course fields = ('task__added_at',) doesn't work here either.
What's the standard approach to something like this? (or am I stretching the Admin too far?)
I'm already using a custom template, so if that's the answer that can be done. However, I'd prefer to do this at the admin level.
If you don't need to edit it, you can display it as a readonly field:
class DownloadAdmin(admin.ModelAdmin):
readonly_fields = ('task_added_at',)
def task_added_at(self, obj):
return obj.task.added_at

Categories