Any alternatives for OneToMany or ManyToOne in Django - python

I have a NOTIFICATION and an USER app in Django.
The code goes something like :
class Notification(models.Model):
user = models.ForeignKey(User , related_name = "notification"
....
....
and
class User(models.Model):
notifications = models.OneToManyField(Notification , related_name = "user"
....
....
Now I know that models.OneToManyField doesn't exist in Django.
I get the fact that I can simply access the user from the notification instance of the model. But I suppose that would somehow slow my system because in production I would keep all the instances of Notification Model.
For example : I'm expecting around 500+ notifications per user once the system is in production for a significant amount of time.
I suppose, it would just be easier to access all the notifications of one user directly rather than sifting through the whole Notification Table to find notifications of a specific user.
I've read this and the documentation to an extent and I'm not able to find a solution to my problem.
Also I'm not sure about the processing constraints of a processor to obtain all the Notifications from the whole Notification Table. I'm just assuming that it'll be somewhat slower.

OneToManyField doesn't exist in Django because it is just the reverse relationship of a ForeignKey. So you don't need the notifications field on the User model here, just remove it.
Don't worry prematurely about performance of filtering on the notifications. Querying relations is what SQL was designed for, and that's what relational databases are good at doing.

Related

Flask - User to Profile Relationships

I'm working with Flask-restplus and I am at a point where I would like to associate each User in my user model to a type of profile, where each user can be associated with one or many profile types. I'm wondering how you guys would go about this. So far, here's what I'm thinking/planning to do. NOTE: I'm not very experienced in web development, so there's a chance I don't know the best way to accomplish this.
Step 1: Create a one-to-many (clients need to also be employees, see below) field (profile_types) relating to a static table that just lists all possible profile options. EXAMPLE:
PK PROFILE TYPE
1 provider
2 employee
3 client
.....
The idea here is to track different information and allow for different views/endpoints for users who are tied to certain profile types. Example, employees would provide a valid login authentication and be directed to page A while a client would be directed to page B, etc. We're also planning on collecting different data points within each profile model.
So an instance of a user might look like this, user1.profile == [client, employee'].
NOTE: This is more important for data collection (ie age of employee, start date, etc) than it is for creating directives based on permissions.
Step 2: Upon creating the new user, a signal fires off the creation of a profile based on the profile_types supplied to the user instance. I've used signals with django in the past, is there a signal library for Flask?
Step 3: An empty profile instance(s) now exists for that user. It will be up to a superuser to upload data in bulk or manually fill out profile information.
Is this a sensible way to go about this? My other though is to create a bunch of Boolean fields in the User model is_provider, is_employee, is_client, etc. All fields that are True get assigned a profile instance. What's the best way to go about this?
Thanks everyone!
Seeing that are you try to validate multiple profile types, you may use
if user.profile_type in ['employee', 'client']
Now, if you want to add an super user I think you can use this
if user.profile_type in ['employee', 'client'] and user.profile_type == 'superuser'
Now, you relationship is more like 'many-to-many', because you are saying that an client also needs to be an employee, if you mean that some endpoints needs to be accessible for employees and clients, then you need to use a 'many-to-one' relationship (an Stackoverflow question which explains what is that)
For your instances, there is Flask Marshmallow, which has an amazing compatibility with Flask SQLAlchemy if you are using an database, but Flask Marshmallow can work alone.

multiple foreign key in a model (One to Many mapping) django python? [duplicate]

I have a NOTIFICATION and an USER app in Django.
The code goes something like :
class Notification(models.Model):
user = models.ForeignKey(User , related_name = "notification"
....
....
and
class User(models.Model):
notifications = models.OneToManyField(Notification , related_name = "user"
....
....
Now I know that models.OneToManyField doesn't exist in Django.
I get the fact that I can simply access the user from the notification instance of the model. But I suppose that would somehow slow my system because in production I would keep all the instances of Notification Model.
For example : I'm expecting around 500+ notifications per user once the system is in production for a significant amount of time.
I suppose, it would just be easier to access all the notifications of one user directly rather than sifting through the whole Notification Table to find notifications of a specific user.
I've read this and the documentation to an extent and I'm not able to find a solution to my problem.
Also I'm not sure about the processing constraints of a processor to obtain all the Notifications from the whole Notification Table. I'm just assuming that it'll be somewhat slower.
OneToManyField doesn't exist in Django because it is just the reverse relationship of a ForeignKey. So you don't need the notifications field on the User model here, just remove it.
Don't worry prematurely about performance of filtering on the notifications. Querying relations is what SQL was designed for, and that's what relational databases are good at doing.

User roles schema on Django

A great greetings community
My question is related with the kind of manage users and the schema users in Django, In beginning I ask to you apologize just in case that my questions can will be too "newbies" or without sense, I am starting to related me with the Django Users schemas and their different possibilities of work in the projects.
I have the following situation.
I am building an application in which I will have three differents user types:
Medical
Patient
Physiotherapist
I am using the default Django authentication scheme (django.contrib.auth).
Initially, I did think in this scheme of entities in which the User table is the auth_user table in where Django save the users created:
I have the is_patient, is_medical and is_physiotherapist fields like boolean attributes in the User table.
Like a particular detail I understand that in the Django default model User is not possible modify or add attributes or fields.
This is an important and powerful reason to I cannot add the is_patient, is_medical and is_physiotherapist boolean fields in User table.
A classic recommendation is extend the User model with a Userprofile table in which I add fields or attributes to User Model through of OneToOne relationship. A basic sample is such as follow:
Is of this way that I get that my users in Django can have the field photo and upload one in a given moment ...
Taking advantage of the previous,
The following schema can be suited or can be an alternative for manage user roles (patient, medical and physiotherapist user types) ?
I will have relationships between:
User medical and user patients
user physiotherapist and user patients
and so between them and other tables ...
With this approach these relationships don't will be affected?
The different users will be saved between the Users and UserProfile table.
Is this a good practice in the scalability sense? My tables could be crash or my database?
In addition, I also have seen other alternatives such as:
Role Table/Model
I will have a role table/model independent or separate and that this can be related with the Django User model (One User can will have many roles by example)
This approach can be useful when I want store exclusive information about of a role in specia?
Django Permissions and Authorization
I ignore or unknown the granularity grade that let will me work. Of a single way I have been see that the permissions and authorizations system let will me work with create and edit and remove operations ....
Here, can I see the groups creation?
For example a medical group and allocate them permissions and linked this permissions to the users that compose the group ? Is this another good alternative?
This option seem more single although I don't know if an user could make some operations according to the group privileges that have ... I don't know if this thinking is correct/right
AUTH_USER_MODEL Creating a Custom User model
My requirements for patient, medical and physiotherapist users, require build a custom user model?
In this situation, especially if you want to store different infos for Patients, Medics and Physiotherapists you can create a Model for each and have a OneToOne field for each to the User model.
class Medic(models.Model):
user = models.OneToOneField(User, primary_key=True)
# other fields
class Physio(models.Model):
user = models.OneToOneField(User, primary_key=True)
# other fields
class Patient(models.Model):
user = models.OneToOneField(User, primary_key=True)
# other fields
This way you can give different permissions/roles implicitly in your application logic for each type of user (and still use the groups and permissions that Django offers if you need them for special cases, eg ChiefMedical...).
You will have to define some methods for your application logic like
def user_is_patient(user):
...
If you follow this path it is a good idea to have good tests to make sure that you don't get unexpected things like a user who is a Medic and a Physio...
Django lets you subclass the user model as well. Under the covers it would do the same thing as the code above, so it is probably better to do it explicitly as shown above (this way it is less probable that you access attributes that don't exist in that object!)
Taking advantage of the previous, The following schema can be suited or can be an alternative for manage user roles (patient, medical and physiotherapist user types) ?
The schema you show isn't great because it makes you store the information for all user types in the same table (and with the same fields). For example, Medics and Physios will have a blood type field type like Patients which will probably not be defined.
The different users will be saved between the Users and UserProfile table. Is this a good practice in the scalability sense? My tables could be crash or my database?
There should be no scalability problems with this solution (as long as you don't have millions new entries writes every day) and you can always optimise the database at a further point. However, you will have to make sure that your app doesn't accept 'forbidden' entries (e.g. users with no Medic, Physio or Patient profile)
Here, can I see the groups creation? For example a medical group and allocate them permissions and linked this permissions to the users that compose the group ? Is this another good alternative? This option seem more single although I don't know if an user could make some operations according to the group privileges that have ... I don't know if this thinking is correct/right
You can (should) use Django's permission system to give permissions to your users. You can use them to give different rights to users of the same type (for example Medics that have more permissions than others... or have groups for chief physios...)
Django lets you assign permissions to a group.
But I don't think groups can replace the custom models for each user, since you want to store information for them. Having custom models and groups would be redundant and make your app harder to maintain.
My requirements for patient, medical and physiotherapist users, require build a custom user model?
This option wouldn't be great (unless it is your only option) because your app won't be reusable and you might have problems with some packages as well.
You can create a custom User model or not, in any case, you could have three separate models for storing pertinent data, depending on whether the user is patient, medical, physiotherapist, or any combination of these.
If your permissions scheme is determined solely by the role (patient, medical, physiotherapist) then you don't need to use Django's permissions system, because you know the role(s) of any user and you can, in the worst scenario, hardcode authorization rules.
I gave a glance at question's comments and I view some issues:
()
I realized that your user model does not match with the original data model since having get_medical_profile, get_patient_profile and get_physiotherapist_profile functions inside user model, with that you are assuming that any user could have multiple profiles at the same time, which isn't reflected neither in your profile models (Medical, Patient and Physiotherapist) using OneToOneField nor in original data model of the question, it's an important thing about abstraction and class-responsibility. The requirement (according the model below) seems to say "one user can have only one profile".
So.. I think this can be solved in a straightforward and clean way, you don't need to involve in overall authentication esquema like groups and permissions or adding additional attributes to user model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
# common fields shared by medical, patient and physiotherapist profiles
class MedicalUser(models.Model):
profile = models.OneToOneField(UserProfile)
# medical fields here
class PatientUser(models.Model):
profile = models.OneToOneField(UserProfile)
# patient fields here
class PhysiotherapistUser(models.Model):
profile = models.ForeignKey(UserProfile)
# patient fields here
As you see, you can have a profile which contains common fields shared by all profiles. and each profile has an specific model.
In addition, you can check if user is medical by this small function below, then if there is no an medical profile associated with profile then it will raise exception and it means it's a profile unspecified:
def is_medical_profile(profile):
try:
profile.medical_user
return True
except:
return False
You can also use it in your templates (as a custom template tag) in this way:
{% if profile | is_medical_profile %}
With this approach you don't need to setup AUTH_USER_MODEL
I hope this improves your solution.
Additional notes:
Just in case you decide to have a custom user model, setup settings.AUTH_USER_MODEL and use it for foreign keys to User.
On a piece of text of awesome book Two scoops of Django says:
From Django 1.5 onwards, the official preferred way to attach
ForeignKey, OneToOneField, or ManyToManyField to User
Therefore, your user profile model would change as follows:
from django.conf import settings
from django.db import models
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
Yes, it looks a bit strange, but that's what the official Django docs advice.
#geoom #Ire #lorenzo-peña I 've created an user through Django admin site and I checked their attributes (is_medical, is_patient, is_physiotherapist) via python shell
In [6]: User.objects.filter(username='agarcial').values('is_medical','is_patient','is_physiotherapist')
Out[6]: [{'is_physiotherapist': True, 'is_patient': True, 'is_medical': True}]
For the moment in my views.py I am doing that an user sign in only when this be one of three user types (medical, patient or physiotherapist)
# Create your views here.
class ProfileView(LoginRequiredMixin, TemplateView):
template_name = 'profile.html'
def get_context_data(self, **kwargs):
self.request.session['Hi'] = True
context = super(ProfileView, self).get_context_data(**kwargs)
is_auth = False
name = None
# Check if in the request goes the user
user = self.request.user
# Check about of possible cases (For now is one profile)
if user.is_medical:
#if self.request.user.is_authenticated():
print (user.is_medical)
is_auth = True
profile=user.get_medical_profile()
#name = self.request.user.username
data = {
'is_auth':is_auth,
'profile':profile,
}
context.update({'userprofile':profile, 'data':data})
elif user.is_patient:
print (user.is_patient)
is_auth=True
profile=user.get_patient_profile()
data = {
'is_auth':is_auth,
'profile':profile,
}
context.update({'userprofile':profile,'data':data})
elif user.is_physiotherapist:
print (user.is_physiotherapist)
is_auth=True
profile=user.get_physiotherapist_profile()
data = {
'is_auth':is_auth,
'profile':profile,
}
context.update({'userprofile':profile,'data':data})
return context
def get_userprofile(self):
return self.request.user.userprofile
If I check the other possible combinations (User patient,medical and physiotherapist) this could work?
I think create groups for (Medicals, Patients, Physiotherapists) and binding users for the authorization topic, although I should review other things for authorization process such as django guardian for example?
How about this?

Django admin hangs (until timeout error) for a specific model when trying to edit/create

This one is driving me nuts right now. It was not happening before (even got screenshots I had to do for the user-manual since the customer required it).
I first noticed it on production server and then I checked and also happens in the dev server that comes with Django. The model appears on the main-page of the django admin, I can click it and it will display the list of point of sales. The problem comes whenever I want to edit an existing instance or create a new one.
I just click on the link (or put it on the bar) and it just hangs.
class PointOfSaleAdmin(admin.ModelAdmin):
list_display = ('id','business', 'user', 'zipcode', 'address','date_registered')
list_filter = ('business',)
filter_horizontal = ('services',)
admin.site.register(models.PointOfSale, PointOfSaleAdmin)
That's the registration of the model. All models are registered in the admin application and the user to test this is a super user. The model is:
class PointOfSale(models.Model):
user = models.ForeignKey(User)
zipcode = models.ForeignKey(Zipcode)
business = models.ForeignKey(Business)
services = models.ManyToManyField(Service,
verbose_name='available services')
date_registered = models.DateField(auto_now_add=True)
address = models.CharField(max_length=300)
Plus a few methods that shouldn't really matter much. Plus, last time before this that I tested the admin was right after I created all those methods, so it shouldn't matter on this.
The administrator very very rarely has to access this page. Usually it's just listing the PoS, but it still bothers me. Any idea of why it could be hanging? All other models are working just fine.
This is happening on both Django 1.2.5 and 1.3
EDIT:
I modified the timeout limits. It IS working, but somehow it takes several minutes for it to actually happen. So, there is something in the background that is taking ages. I don't understand how come it happens only for this model and it happens in different environments (and with small datasets)
I almost feel like slapping myself. My fault for not sleeping for so long.
The problem is that the zipcode list is pretty big (dozens of thousands) and the foreign key field is loaded as an html select tag, which means it loads every single entry. It's an issue with how much data there is simply.
Now I wonder how to control the way the foreign key is displayed in the admin. Anyone could help with that?
In your admin.py file, under the appropriate admin class, set
raw_id_fields = ('zipcode',)
This will display the zipcode's PK instead of a dropdown.
Is there a reason that you are setting up zipcode as it's own model instead of using a CharField or an actual zipcode modelfield?
I just wanted to add that another option here is creating a read_only_fields list. In cases where there is a relationship to a model with a large number of choices(in my case a rel table cataloging flags between a large number of users and discussion threads) but you don't need to edit the field. You can add it to the read_only_fields list will just print the value rather than the choices.
class FlaggedCommentsAdmin(ModelAdmin):
list_display = ('user', 'discussion', 'flagged_on')
readonly_fields = ('user', 'discussion')
For people still landing on this page: As Mamsaac points out in his original post, the timeout happens because django tries to load all instances of a ForeignKey into an html-select. Django 2 lets you add an auto-complete field which asynchronously lets you search for the ForeignKey to deal with this. In your admin.py do something like this:
from django.contrib import admin
from .models import Parent, Child
#admin.register(Parent)
class ParentAdmin(admin.ModelAdmin):
# tell admin to autocomplete-select the "Parent"-field 'children'
autocomplete_fields = ['children']
#admin.register(Child)
class ChildAdmin(admin.ModelAdmin):
# when using an autocomplete to find a child, search in the field 'name'
search_fields = ['name']
Have you tried checking the apache logs (if you're using apache obviously) or any other HTTP server related logs? That might give you an idea of where to start.
That's the only model that is affected? You mentioned methods on the model. Try commenting out those methods and trying again (including the __unicode__ method), just to see if they somehow affect it. Reduce everything down to the bare minimum (as much as possible obviously), to try and deduce where the regression started.
Try to monitor server resources when you request this page. Does CPU spike dramatically? What about network I/O? Could be a database issue (somehow?).
Sorry this doesn't really answer your question, but those are the first debugging techniques that I'd attempt trying to diagnose the problem.

Django ModelForm, having a foreign key as a hidden field

I'm basically building a very trivial form. Let's stick to the books/publisher examples given in the django tutorials and build upon that.
I have a user login to the web app, at which point the first thing they can do is click on a publisher. This publisher then gets saved for their session. Upon that I take them to a create book form. In there I embed the the publisher's id from the database into a hidden field.
Upon the user submitting an HTTP POST, I do something like:
mybookform = BookForm(request.POST)
if mybookform.is_valid():
abook = mybookform.save(commit=False)
abook.publisher_id = request.POST['publisher_id']
mybookform.save()
Yes there's a few naive things done here, such as blindly grabbing the publisher_id and verifying if it's indeed a real publisher id, amongst other security issues. Let's just not pay attention to that for the moment.
My question is, is there a better way of handling this? Although hypothetically this example doesn't make logistical sense, in my particular app the example actually makes sense. The problem is I get a ValueError exception saying publisher_id needs to be a Publisher instance.
Now I can easily retrieve a publisher instance with Publisher.objects.filter(id=..) and use that instead. The question is, is it really necessary? Can I avoid the additional query to the database and somehow update this form instance in a more 'elegant' fashion?
Also, is it possible to somehow embed the publisher in a hidden field so that I do not need to do mybookform.save(commit=False) and just do mybookform = BookForm(request.POST) followed by mybookform.save() immediately?
Retrieving the instance of the publisher does protect against client-side changes that might reference a completely invalid publisher.
To your second question, yes you can include that field as a hidden field by overriding the field in the ModelForm with the approriate form field setting the widget to HiddenInput.
There is no better way to do this.
I would use the get_object_or_404 function for this.
And yes, you can prevent this to be modified by the user by setting the model field to editable=False,

Categories

Resources