Multiple permission to view/add/change a model class object - django

I am trying to edit permissions from the admin-site for a specific group in my project. (Specifically the Manager group)
I noticed that for this one model class named DeliveryOrderForm, contains two instances of one permission.
For example :
deliveryorder| delivery order form | can add delivery order form
deliveryorder| delivery order form | can add delivery order
What I understand is that the first part 'deliveryorder' is referencing the application name, the second part is referencing the model's class name, but I am unsure what the 3rd part is referencing to.
These are the attributes for my class DeliveryOrderForm model
class DeliveryOrderForm(models.Model):
deliveryOrderID = models.AutoField(unique=True,primary_key=True)
vendorName = models.CharField(max_length=30)
vendorAddress = models.CharField(max_length=200)
recipientName = models.CharField(max_length=30)
recipientPhone = PhoneNumberField(blank=False)
recipientAddress = models.CharField(max_length=200)
deliveryOrderStatus = models.IntegerField(default=Status.pending,choices=Status.choices)
deliveryOrderDate = models.DateTimeField(default=timezone.now())
I hope someone can help me understand this cause I'm afraid if my model is actually screwed up.
Edit : Turns out, the old permissions retained after I renamed the model class from DeliveryOrder (previous class name) to DeliveryOrderForm (current class name). Removing the old permissions should solve this.

Related

Django Graphene hiding a model field (or return null) based on user preference in ManyToMany

assume we have the following Django Models:
class Person(models.Model):
name = models.CharField(max_length=255)
personal_field = models.CharField(max_length=255)
class Group(models.Model):
name = models.CharField(max_length=255)
participants = models.ManyToManyField(
"Person",
through="GroupPersonOption",
through_fields=('group', 'person')
)
class GroupPersonOption(models.Model):
person = models.ForeignKey("Person", on_delete=models.CASCADE)
group = models.ForeignKey("Group", on_delete=models.CASCADE)
hide_personal_field = models.BooleanField(default=False)
Example:
Based on the group a user is in, they can choose to hide their personal_field, so that instead of its regular value, None or Null is returned.
The Person can set this in the ManyToMany Model called GroupPersonOption
Where it gets tricky:
How do I change its value to None in my DjangoObjectTypes?
When I try to add a resolve function for the personal_field in PersonObjectType, I don't know if the user wanted to hide this info.
Graphene Code:
{
peopleByGroup(name: "DjangoIsAwesome") {
person {
name
personal_field
}
}
}
I have waited a few days in the Django Subreddit but the only solution one person came up with was just to ignore setting the personal_field to None based on some value and then hide it in the frontend, however that is not an acceptable solution, as this would expose user data.
I have also tried adding a resolve_person function to the PersonEventOptionType, but that broke a lot of things, as I could not find an example of resolving foreign keys in a ManyToMany DjangoOjectType.
Any help is appreciated.
Thanks for your time.

Using OneToOneField with multiple versions of data

I want to have two versions of the same model while still benefiting from OneToOneField's reverse relation.
For example, let's say that I have the following models:
class Company(models.Model):
exists = models.BooleanField()
class ExtraInforation(models.Model):
company = models.OneToOneField(Company)
wealthy = models.BooleanField()
At this point my code uses the brilliance of the OneToOneField reverse relation, doing company.extrainformationcalls all over the place.
Then I get a new requirement: we can't trust the ExtraInformation without verifying it first! Pfft, any company could claim that it's wealty...
Any changes to ExtraInformation need to be confirmed before publishing. Let's say that the company isn't wealthy when it registers and that information gets confirmed. Later the company wants to mark itself wealthy. At that point there needs to be the confirmed/public version of ExtraInformation and the unconfirmed version that needs to be confirmed.
I want to be able to still keep those handy OneToOneField reverse relation calls but also have another version of the same data. The problem is, of course, that there can be only one row with reference to this company in the OneToOneField.
Currently my solution is to create a new table:
class ExtraInforationUnconfirmed(models.Model):
company = models.OneToOneField(Company)
wealthy = models.BooleanField()
Once the information is confirmed, the fields are copied from ExtraInforationUnconfirmed to ExtraInformation. This solution isn't very DRY or clean.
What would be the best way to solve this issue?
I studied proxy models and model inheritance. The best alternative way I could think of is to have a base model and inherit two models that have both have OneToOneField relation of their own to Company.
Add a boolean feild to the model and change it to true when confirmed:
class ExtraInforation(models.Model):
company = models.OneToOneField(Company)
wealthy = models.BooleanField()
confirmed = models.BooleanField(default=False)
UPDATE
Based on your comment I suggest a version filed which can be a simple integer or a datetime. I would avoid creating two models at any cost :)
class ExtraInforation(models.Model):
company = models.ForeignKey(Company, related_name='extrainformations')
wealthy = models.BooleanField()
# version = models.PositiveIntegerField()
version = models.DateTimeField(auto_now_add=True)
confirmed = models.BooleanField(default=False)
You can add a property to Company that returns the last extrainformation so that company.extrainformation will still work:
#property
def extrainformation(self):
return self.extrainformations.order_by("-version").first()

Django many-to-many lookup from different models

I have some models that represents some companies and their structure. Also all models can generate some Notifications (Notes). User can see own Notes, and, of course, can't see others.
class Note(models.Model):
text = models.CharField(...)
class Company(models.Model):
user = models.ForeignKey(User)
note = models.ManyToManyField(Note, blank='True', null='True')
class Department(models.Model):
company = models.ForeignKey(Company)
note = models.ManyToManyField(Note, blank='True', null='True')
class Worker(models.Model):
department = models.ForeignKey(Department)
note = models.ManyToManyField(Note, blank='True', null='True')
class Document(models.Model)
company = models.ForeignKey(Company)
note = models.ManyToManyField(Note, blank='True', null='True')
The question is how I can collect all Notes for particular user to show them?
I can do:
Note.objects.filter(worker__company__user=2)
But its only for Notes that was generated by Workers. What about another? I can try hardcoded all existing models, but if do so dozen of kittens will die!
I also tried to use backward lookups but got "do not support nested lookups". May be I did something wrong.
EDIT:
As I mentioned above I know how to do this by enumerating all models (Company, Worker, etc. ). But if I will create a new model (in another App for example) that also can generate Notes, I have to change code in the View in another App, and that's not good.
You can get the Notes of a user by using the following query:
For example let us think that a user's id is 1 and we want to keep it in variable x so that we can use it in query. So the code will be like this:
>>x = 1
>>Note.objects.filter(Q(**{'%s_id' % 'worker__department__company__user' : x})|Q(**{'%s_id' % 'document__company__user' : x})|Q(**{'%s_id' % 'company__user' : x})|Q(**{'%s_id' % 'department__company__user' : x})).distinct()
Here I am running OR operation using Q and distinct() at the end of the query to remove duplicates.
EDIT:
As I mentioned above I know how to do this by enumerating all models
(Company, Worker, etc. ). But if I will create a new model (in another
App for example) that also can generate Notes, I have to change code
in the View in another App, and that's not good.
In my opinion, if you write another model, how are you suppose to get the notes from that model without adding new query? Here each class (ie. Department, Worker) are separately connected to Company and each of the classes has its own m2m relation with Note and there is no straight connection to User with Note's of other classes(except Company). Another way could be using through but for that you have change the existing model definitions.
Another Solution:
As you have mentioned in comments, you are willing to change the model structure if it makes your query easier, then you can try the following solution:
class BaseModel(models.Model):
user = models.Foreignkey(User)
note = models.ManyToManyField(Note)
reports_to = models.ForeignKey('self', null=True, default=None)
class Company(BaseModel):
class Meta:
proxy = True
class Document(BaseModel):
class Meta:
proxy = True
#And so on.....
Advantages: No need to create separate table for document/company etc.
object creation:
>>c= Company.objects.create(user_id=1)
>>c.note.add(Note.objects.create(text='Hello'))
>>d = Document.objects.create(user_id=1, related_to=c)
>>d.note.add(Note.objects.create(text='Hello World'))

Creating and saving non-empty Django model instance as part of subclass instance

I am experiencing a very strange behavior inconsistent with the Django documentation while creating and saving (inserting into DB) model instance. I've already run out of ideas for possible reason and will be very grateful for any suggestions why Django fails to save all fields in these cases.
This class I am using:
class Person(models.Model):
user = models.ForeignKey(User)
phone_number = models.CharField(max_length=20, blank=True)
address = models.CharField(max_length=200, blank=True)
And here's code that does't work, few cases:
# First Case
new_person = Person()
new_person.user = request.user
new_person.phone_number = '111111'
new_person.save(force_insert=True)
# Second One
new_person = Person(user=request.user, phone_number='111111')
new_person.save(force_insert=True)
# Third One
new_person = Person.objects.create(user=request.user, phone_number='111111')
Basing on official Django docs in any case django should create an object and insert it into DB.
In fact the object is successfully created (and all relevant fields are set), but row inserted into DB has only id and user_id fields filled correctly while phone_number field that was also set, remains blank.
There is, however, no problem to access and update all fields of existing (saved earlier) objects.
Removing blank=True from Person class declaration (with proper table alteration) does't change anything.
EDIT:
Problem turned out to be more sophisticated. Full description and solution in my own answer beneath
Ok, I found an explanation....
It has something to do with inheritance, namely further in the code I wanted to create instance of Person's subclass. So there was another class:
class Person(models.Model):
user = models.ForeignKey(User)
phone_number = models.CharField(max_length=20, blank=True)
address = models.CharField(max_length=200, blank=True)
class ConnectedPerson(Person):
connection = models.ForeignKey(AnotherClass)
# etc..
And after creating instance of Person, intending to extend it to ConnectedPerson I made such code:
#creating instance of Person:
person = Person(user=request.user, phone_number='111111')
person.save(force_insert=True)
c_person = ConnectedPerson(id=person.id, connection=instance_of_another_c)
and using ConnectedPerson(id=person.id) was in fact killing previously created Person instance by overwritting it in the DB.
So for anyone not too much experienced in managing inheriting instances: if you need to use earlier created super class instance as part of subclass instance do it this way:
#creating person but not saving it
person = Person(user=request.user, phone_number='111111')
######
#later
######
#creating subclass instance and saving
c_person = ConnectedPerson(user=request.user, connection=instance_of_another_c)
c_person.save()
#saving super class instance as part of subclass instance
person.pk = super(ConnectedPerson, c_person).pk
person.save()

TastyPie Resource include Set Items

I was wondering what is the best way to include objects from another model that are related on a foreignkey?
Example:
class First(models.Model):
name = models.CharField(max_length=255)
class Second(models.Model):
first = models.ForeignKey(First)
second = models.CharField(max_length=255)
How would I create a resource for the first model that includes all the related objects in the second one? - I know how to do it for foreignkeys in the first one, but not sure about how to go about this.
Cheers,
Ben
Put this on the resource that wants reverse relation
anyfieldnameyouwant = fields.ToManyfield(FooResource, 'relatedname', full = True)
In this case:
class FirstResource(ModelResource):
second = fields.ToManyField(SecondResource, 'second_set', full = True)