Django: Want a ManyRelatedManager, getting ManyToManyField instead - django

So in my project I am trying to extend the User model to a Staff class and the Group model to a PermGroup class. However, when I save a PermGroup in the Staff's groups field (inherited from User) it only saves the PermGroup object as a Group and all of the fields and methods I defined in my PermGroup class are stripped away. So I decided the best course of action would be to override the groups field. From an earlier stackoverflow question I found and Django documentation, this should work.
class Staff(User):
User.groups = models.ManyToManyField('PermGroup', blank=True)
I need to use 'PermGroup' because the class shows up later in the file, and PermGroup has a field that relies on the Staff class, so if i switched the order I would have the same problem, only in the PermGroup class.
Now the problem I am having is that groups is now a ManyToManyField object where all the other "manytomany" fields are ManyRelatedManagers. I want groups to be a ManyRelatedManager but I do not know how.
Is it possible to get groups to be a ManyRelatedManager when I initiatize it using the 'PermGroup' model call?
If my approach is wrong and you can suggest an alternative to saving PermGroups in the Staff class. I would greatly appreciate it.

Why not just have your Staff be a standard model with a ForeignKey (OneToOneField, to be more exact) to his/her corresponding User?
And, to remove the circular dependency problem, you just need to make one dependent on the other. For instance, the PermGroup model could have a field of a ManytoMany of the Staff members in that group. There's no need for Staff to have a PermGroup, because if you wanted to see what groups a member belongs to, you'd just do something like this:
groups_theyre_in = PermGroups.objects.filter(staff_members__id=id_were_looking_for)

Related

Is there any possibility to add fields inside the fields of a Model

Assume I have a model named MyModel and I have a Field Named field Now I want to add three more fields inside the prescription like one field_a , field_b and field_c .
Does Django Allow that in any way or we have to make another model for this purpose and then link with Foreign Key to MyModel?
Well I think it is an idea that could lead to some really hard to maintain code and should be well thought through.
That aside If you have a look at:
https://docs.wagtail.io/en/stable/topics/streamfield.html
It's a special field meant for cms applications that uses json in the field to model dynamic fields and validations for it.
Also if you run postgres this might help. https://docs.djangoproject.com/en/3.2/ref/contrib/postgres/fields/#jsonfield

Django - get linked models in many to many

I have two different models:
A group model
class Group(models.Model):
(...)
users=models.ManyToManyField(users.User, related_name='trainings')
And a very standard user model.
I'm trying to write a function where it returns all of the linked groups for a given User object.
What would solve my problem is something like this:
def get_groups(user):
connected_groups = Group.objects.filter(user in users)
But that throws an error. It the thing that I am trying possible? Or should I instead create a 'linked_groups' variable within the User model?
Check the documentation here: https://docs.djangoproject.com/en/1.11/topics/db/queries/#many-to-many-relationships
Both ends of a many-to-many relationship get automatic API access to the other end. The API works just as a “backward” one-to-many relationship, above.
The only difference is in the attribute naming: The model that defines the ManyToManyField uses the attribute name of that field itself, whereas the “reverse” model uses the lowercased model name of the original model, plus '_set' (just like reverse one-to-many relationships).
For any User called u in your application, u.group_set.all() will be a queryset of all Groups with a many-to-many relationship to that user. Since you have defined a related_name you can use the more readable syntax u.trainings.all().

Should Entry.author be a ForeignKey to User or UserProfile?

In Django, I want to filter a QuerySet using a list of Users who the active user is following.
I've opted to extend the User class rather than replace it with a custom class, although I'm not sure that was the right choice.
Hence what I have is a UserProfile class, which has a ManyToManyField to other UserProfiles, and a OneToOneField with User.
My QuerySet looks like Entry.objects.filter(author__in=request.user.userprofile.following.all()) but author is a ForeignKeyField to User rather than UserProfile, so I'm about to change Entry.author to point to UserProfiles instead.
So my questions are, in decreasing priority:
Is it right to have author be a UserProfile instead? Because then I have something like entry.author.user.username which is not intuitive.
Might it be better to just replace the builtin User class with a custom class which has the data I need?
Is it right for UserProfile's following to be a ManyToManyField to other UserProfile rather than to User?
I don't recommend this at all. As you said it's not intuitive, an
author should be a user.
No, a one to one relationship to user is better than creating a custom user class.
I think it will look better if you connect followings to users. This way your original query will also work.
In UserProfile model:
following = models.ManyToManyField(User, related_name="followed_by")
In this scenario user.followed_by is a list of UserProfiles, but user.userprofile.following is a list of users.
Since your users can follow each other and Entries are from those people, it makes totally sense to make the author UserProfile so that both models are logically in the same level

Hide primary keys or ids from being exposed

Currently while adding, editing or deleting a object i am using the id (pk) of the object in the urls which of course exposes the global primary key id of that particular object to the users. I somehow want to hide those global id's from the urls and/or from the hidden fields within a form while using POST.
Just to make it a little more clear let me explain this with an example. So say i have the following models.
Models.py
class Profile(User)
# Some fields here
class Student(Profile)
# some fields here
class Teacher(Profile)
# Some fields here
class Project(models.Model)
student = models.ForeignKey(Student)
# some more fields here.
according to the above models, say i want to either edit or delete an existing Project instance. what I currently do is use the id(pk) as an argument in the urls as follows:
Urls.py
url(r'^project/(?P<id>\d+)/edit/$', 'app.views.edit_project'),
url(r'^project/(?P<id>\d+)/delete/$', 'app.views.delete_project'),
what would be the best approach to either completely hide these id's from the url?
is there a way we could have Project Id's per student ? something like adding another auto_increment column to the Project table ?
The SlugField() option proposed by Antony is a great idea. Put a unique constraint on the field (unique=True in your model definition). Then write your urls.py rules like this:
url(r'^project/(?P<slug>[A-Za-z0-9_\-]+)/edit/$', 'app.views.edit_project'),
url(r'^project/(?P<slug>[A-Za-z0-9_\-]+)/delete/$', 'app.views.delete_project'),

Django model ManytoMany getters

I wanted to get a list of objects associated to model A by ManyToMany with model B, e.g. diners (A) confirmed to attend a meal(B). But I'm not sure what getter I should use. I actually wanted to do this to show the associated objects in the admin panel. The method included beneath was one failed attempt I made.
class Meal(models.Model):
diners = models.ManyToManyField(User, through='Attendance', related_name="eating", blank=True)
def diners(self):
return self.eating
Can you help?
Thanks
As ilvar suggested, remove diners method and use self.diners.all() to get objects inside Meal methods. related_name='eating' is for fetching attended meals of a user, reversely.
I arrived at this page with the same problem as OP. I ended up simply removing the reference to the ManyToMany field in list_display in my admin model. The result: on the admin page for that app, under the ManyToMany field name, appeared a nicely formatted multi-selection list widget with the possible values for my ManyToMany relationship shown.
So the solution was to remove the reference in list_display and let Django handle it. This is with Django 1.4.3.