Django Inlineformset with editable Foreign Key Relation - python

I'm trying to create a formset of related objects, where the relation itself is also an editable field.
Let's say we have a models.py like the one below.
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=45)
class Book(models.Model):
name = models.CharField(max_length=45)
author = models.ForeignKey(Author)
Is there a good, pythonic way to create a formset of all Books by a certain Author, and be able to change the Author of any of those books? This would be a particularly useful way to fix any errors in the foreign key relations.
My first instinct was that inlineformset would solve this for me, but I can't seem to get the Author of each book to be an editable field, even when I use custom forms.

using modelformset_factory will do the trick. (pulled from my comments here for completeness of the systems question/answer model)

Related

When to use each model relationship in Django?

I've been reading through the Django documentation and looking over some of the other answers on the site for a couple of hours now, yet I still can't get it to sink in. I know this isn't Django specific, but the examples I use will be from a Django project.
My question boils down to when is it appropriate to use each:
Many-to-many relationships
Many-to-one relationships
One-to-one relationships
One-to-one, more or less makes sense to me.
Now for the other two. While I understand the differences between them in isolation, when it comes to using them practically in a project, I get confused. Here is an example:
class User(AbstractUser):
pass
class Listing(models.Model):
title = models.CharField(max_length=64)
description = models.TextField()
class Watchlist(models.Model):
user = models.ForeignKey(User, related_name='watchlist', on_delete=models.CASCADE)
item = models.ManyToManyField(Listing)
class Comment(models.Model):
user = models.ForeignKey(User, related_name='comments', on_delete=models.SET_NULL)
comment = models.TextField()
Would this be the correct use of Many-to-one(ForeignKey) and Many-to-many?
Should Watchlist.item be a ForeignKey? Or is M2M correct?
Wouldn't it simplify to make the 'Watchlist' part of the User class? (give them an empty list to populate with listing ID's)
Why is Watchlist.user not a One-to-one relationship, if each watchlist belongs to a single user, and a user can only have one list?
Apologies for my stupidity, I just can't get this to sink in!
Thank you.
edit: Context, the models are from a 'learning' project I was working on intended to be an auction site, similar to eBay. The watchlist is sort of a 'wish' list... for the user to watch an item, not for site to watch a user!
To explain it simply these django-models or objects represents tables in your database and the fields are like the columns in them. So with a one-to-one relation you can only have one row in one table relating to one row in another table. For example one user in the user table (represented by one row) can only relate to one row in a profile table. But your user can have many comments, so this would be a one-to-many/foreignkey relation (if you set unique=true on a fk, it will in practice function as 1:1). If the users can collaborate on writing comments, or for example as here on stackoverflow where users can edit other users comments, that would be a many-to-many relation.
Database design can be complicated/complex, especially using an ORM without basic knowledge of SQL and how it all works beneath. In general it requires a bit of planning even for a simple application.

Django admin edit integer field

I have a model with two integer fields which are supposed to be foreign keys. In my admin view, those two fields are editable but I would like to display a search icon next to the field, so I can retrieve the id of another model and append to the field. Does django have this feature?
class Linkage(models.Model):
user_id = models.IntegerField(default=1)
parent_id = models.IntegerField(default=0)
If your model has 2 fields that should actually be foreign keys, then you need to use ForeignKey instead of IntegerField as so:
from django.db import Models
from app.models import yourModel
class Linkage(models.Model):
user_id = models.ForeignKey(yourModel)
parent_id = models.ForeignKey(yourModel)
This Django feature will take care of linking your Linkage to your other model of choice automatically. In the admin, you will no longer need to set an integer with the id of the foreign key, you will be able to simply select an instance of the linked model.
You can read more about Django fields references here.
EDIT: In the way you designed yoour models, there might for example not be a parent_id, so you can add options such as null=True to the parent_id field as so:
parent_id = models.ForeignKey(yourModel, null=True)
I strongly recommend that you read the Django documentation, it is really good for beginners as it is very detailed and clear. You can access the documentation here.
They also have a set of tutorials to get you through the steps and introduce you to the different basics you need to know to get started with Django here.

Django Models Generic Relations

I'm confused with generic relationships in Django.
I have a comment model, and I want both Workflow and WorkflowItem models to be able to have multiple comments.
If I do:
class Workflow(models.Model):
comments = models.ManyToManyField(Comment)
class WorkflowItem(models.Model):
comments = models.ManyToManyField(Comment)
then what do I put in the comment class to link the comment to one of these based on which it is or do I need generic relationships?
Also say I want to put members who are part of the Workflow model, do i do
class Workflow(models.Model):
comments = models.ManyToManyField(Comment)
members = models.ManyToManyField(Person)
or something else?
As you mentioned that you need to link comment back to either Workflow/WorkflowItem, I believe you can structure your models as below
class Workflow(models.Model):
members M2M field
class WorkflowItem(models.Model):
fields
class Comment(models.Model):
name_of_your_generic_fk(Can be either Workflow/WorkflowItem or any content type for that matter)
fields
Using models structure like this you can trace from comment if it was made on Workflow/WorkflowItem.
You can obviously devise a better solution if you put more thought into it!! :)

Using forms in Django

I am creating a website and have two forms. The database I have has authors and titles. What I want to do is when I click the author in my choice field, I want the titles to be filtered so the user can only select those. How would I do this?
class ArticleForm(forms.ModelForm):
author = forms.ModelMultipleChoiceField(queryset=Article.objects.all())
title = forms.ModelMultipleChoiceField(queryset=Article.objects.filter(author=author))
class Meta:
model = Article
fields = ('author','title')
When I click the author name, the title still remains blank. What should I do?
Below is my model
class Article (models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=200)
First you need a relation between the article and author. If you have models like this:
class Author(models.Model):
name = models.CharField(max_length=200)
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author)
Than an Article belongs to an Author and a Author can have many Articles.
A modelForm based on the Author model lets you add (or modify) an author. A modelForm based on Article lets you add (or modify) an article. Thats all very useful but not in this case. We need a normal form with ModelChoiceFields to select author and article:
class ArticleForm(forms.Form):
author = forms.ModelChoiceField(queryset=Author.objects.all())
article = forms.ModelChoiceField(queryset=Article.objects.all())
This form will have a select widget for both author and article field. It let's you select one of each. It will render all authors and all articles to template. That's okay if you have a few, but will be problematic with many entries.
The next part is to filter the article choices. The answer to this is a bit harder. Because it depends on your project requirements.
You might want to write some JavaScript to filter the select fields
based on author.
You might want to add a validator for fields that
depend on each other.
You might not want to load all articles in
advance and might want to use Ajax techniques to load the articles
belonging to an author.
You might want to use the FormWizard to split your form in multiple pages/steps.
...

Django ModelForm - Allowing adds for ForeignKey

I'm trying to mimic the functionality from the Django Admin tool where it allows you to add objects for foreign keys (a little plus icon next to a dropdown). For example, let's say I have the following:
class Author(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Blog(models.Model):
name = models.CharField(max_length=50)
author = models.ForeignKey('Author')
When I go to add my first Blog using a ModelForm for Blog, it shows a dropdown next to Author. However, I have no Authors in the system so that dropdown is empty. In the admin tool, I believe it puts a little "+" icon next to the dropdown so you can quickly and efficiently add a record to the dropdown by opening up a popup.
That is extremely useful, and so I'd like to mimic it in my own app using ModelForms. Is that also built into Django's ModelForms? If so, how do I use it? I can't seem to find anything in the documentation.
You will need to work with: django.contrib.admin.widgets.RelatedFieldWidgetWrapper
This post certainly will guide you:
Django admin - How can I add the green plus sign for Many-to-many Field in custom admin form

Categories

Resources