Django - separate authentication backend code from implementation - django

What is the best way to separate your authentication backend logic from code which is inherently dependent on it?
Here's a common problem: django_auth_ldap does not prepopulate the users table, but rather authenticates against LDAP and adds users to the table as they log in for the first time.
However, say we're writing an app that involves adding members to projects. Users may want to add other users who exist in LDAP but have not logged in before, so you're pretty much required to enter a username in this case and query LDAP and the database to see if that user exists. Again though, if we're writing the app to be reuseable, we'd like the "lookup by username" subroutine to be configurable.
At work we've had two different solutions to the problem which both work fine but they are sort of weird solutions.
Make it so you can write a get_user_by_username function in settings.py which does whatever lookups you want
Give a "appname.modelname" path to a proxy model of auth.User you've created which is expected/forced to have a classmethod which does the same things as get_user_by_username
I think the first one is a little cleaner since it doesn't introduce new types, but it's still a weird thing to have in settings.py.

I suggest writing an abstract base class that encapsulates the expected functionality. This acts somewhat like an interface does in programming languages like C# and Java. Then have a django setting that specifies the class to be used for the get_user_by_username provider.
This means that future developers can put their get_user_by_username implementation anywhere they see fit as long as it is implemented in a class derived from the abstract base class and they point to it in settings.

Related

Creating templates for authentication forms in Django 1.7

First off, I'm very much a newbie when it comes to Django.
The problem I'm struggling with is in trying to create templates for the built-in authentication forms in Django 1.7 but there is very little that I can find in the way of concrete examples anywhere in the documentation or elsewhere.
I can find plenty of questions and examples that describe how to manually create the templates (or copy them from the Django packages) but from what I understand about the Form class and the built-in authentication forms is that I don't need to manually create the actual form in the template. In fact, it seems more desirable to use the Form classes because that would add ensure that fields are named correctly, that the validation such as max length on text fields is applied, etc.
Can anyone point me to some concrete examples or documentation of what I'm talking about? I've read the following sections already,
https://docs.djangoproject.com/en/1.7/topics/forms/
https://docs.djangoproject.com/en/1.7/topics/auth/default/
https://docs.djangoproject.com/en/1.7/topics/auth/customizing/
In fact, I would say that this question extends to any Form class in general but I'm specifically looking at the authentication forms here because I obviously haven't written these Form classes.
I don't think it should make any difference from what I've read since the same process should apply, but I will say that I'm using the django-authtools package (http://django-authtools.readthedocs.org/en/latest/)
I have the actual authentication system working fine. It logs users in and out, I can enforce that certain urls require the user to be logged in first, etc. so its only the actual form display that is an issue.

django: routing users through a complex app with class-based views

I'm an advanced beginner at django and python. I'm writing an app to handle registration and abstract submission for a conference, and I'm trying to use class-based views. Users get an emailed link that includes their registration code in the url. Starting at this url, users move through a series of views that collect all the necessary info.
The complication comes from the fact that users often stop half way through, and then want to complete the process several days or weeks later. This means that they might continue from the current page, or they might just click that original link. In addition, after several weeks they might have missed certain deadlines, so, e.g., they can no longer submit an abstract (but they can still register). Along the way, they have checked or unchecked various options that also influence the path they should take through the app.
My question is: where is the best place to put the logic that determines if the user is currently allowed to view that page, and if not, the best url to redirect them too? I thought I would create a custom view class that, e.g., overrides the dispatch method to include global checks (e.g., is conference registration open?), and then subclasses could add additional checks (e.g., has the user entered all the necessary info for her abstract?). The problem I ran into was that the checks were run in the wrong order (I want base class checks run first). I then started investigating custom view decorators or custom middleware. At this point I realized I could use some expert advice about which approach to take. (If it matters, I am not using the django authentication system.) Thanks in advance.
Maybe the form wizard could help you managing the viewing sequence.
In general django greybeards advocate keeping row-wise logic in Models, and table-wise logic in Managers, so it seems appropriate to keep complex view logic in a master view class.
The wizard class can help maintain the order of the views, but to resume an out-dated session you may need to do some model saves (which could get too complex very quickly) or some cookie handling.
In the past, when presented with a similar situation, I took the simplest route and separated user registration and the task that the user wants to perform (event registration). The user registers once but if they fluff up the event registration, they just have to log back in at a later date and do it again (their hassle - not yours!).

What is better way to have multiple type of member profiles in django

I see another question on stackoverflow.com whose title seems similar but that doesnot fulfil my requirements and my users are very different so only different roles will may be not work well. I have scenario of job portal where one type of user is a company which have different attributes different functionality while other is candidate who can show his profile and resume e.t.c., they will have different URLs. So they are totally different but common thing is that they are both Registered users. They will use login forms, they will have change password and I intend to use User class for that purpose.
Actual problem I am facing is about UserProfile class usage. UserProfile is use for profiles but in my case these two users are totally different and need many different things in profile. Also I will may be add more user types in system in future. While in django, we tell about profile is by adding this single model in settings.py
AUTH_PROFILE_MODULE = ‘accounts.userprofile’
So is there a way to do this by using some sort of inheritance or abstract class in django or some other way so that I can get intended functionality and can use django Profiles?
EDIT: Ok, upon further inspection, my previous answer clearly will not work.
I had advocated abstracting the UserProfile class. However, if you do that, you cannot instantiate it, so you're back to square one.
However, you can use Multi-table inheritance to achieve what you want. See this in the docs and this Quora thread that provided the inspiration.
The code I posted before remains largely unchanged, save for the exclusion of the Meta sub-class and the abstract variable.
class UserProfile(models.Model):
# Some Stuff
class CompanyProfile(UserProfile):
# Some more stuff
class CandidateProfile(UserProfile):
# Even more stuff

Avoiding circular dependencies in Django applications

While working on my Django-based projects I'm always trying to follow Django's approach to reusable apps - I'm trying to decouple my applications from each other and especially trying to avoid cross references but sometimes it does not seem to be possible.
Let's consider a simple example with 2 applications: articles and users. Articles application defines article model, articles list view and single article view, users application defines user model and user profile view. Article is referencing user from the author field, so articles application is obviously dependent on users application which is fine.
But when it comes to user profile, I want to display latest articles authored by the user (and may be latest articles viewed by the user) on that page but that makes users application aware of articles application which is what I'm trying to avoid.
I can obviously try to push all such references to the template level but it still does not solve the issue completely and at the same time may be very inefficient in terms of database queries sometimes.
What do you guys do in such cases?
If you are really set on not having any conversation between the 'user' app and the 'article' app, then you need a third app to act as interface. That would know about users and articles and define all the coupling between them. Your article view would be in there, since it has to get the user data, and your user profile view would be in there, because it needs to say "Fred wrote 5 articles".
Whether this level of decoupling is worth it, I don't know. Sometimes programming for re-usability gets in the way of making the thing usable in the first place.
The standard (or preferred) way of keeping coupled apps decoupled is to add a conditional coupling - like in some apps that try to import django-notification and only if they find it, they report events to it.
Still, if you have two apps that talks to each other by design, then I don't see any point in decoupling them - there are plenty of examples in Django world of apps that just require other apps. Note that I'm talking here about writing real-world software, not about some academic delibrations :-)
It seems that in this case, the dependency of users on articles is in a method, not a field. (Whether it's a model method, a model class method, or a manager method is immaterial). If that's so, you can do a lazy import of articles inside the method. By the time this import is performed, users.models will be fully loaded, so even if this is a circular import, it will not cause problems. The "import users" statement in articles will not have to re-load users and will have the full users namespace available.

Django: django-transmeta - sorting comments

I have created an article site, where articles are published in several languages. I am using transmeta (http://code.google.com/p/django-transmeta/) to support multiple languages in one model.
Also I am using generic comments framework, to make articles commentable. I wonder what will happen if the same article will be commented in one language and then in another. Looks like all comments will be displayed on both variants....
The question actually is:
Is there a possibility to display only comments submitted with current language of the article?
I tried the approach of transmeta for translation of dynamic texts and I had the following experience:
You want another language, you need to change the database model which is generally undesirable
You need every item in both languages, which is not flexible
You have problems linking with other objects (as you point out in your question)
If you take the way of transmeta you will need two solutions:
The transmeta solution for translating fields in a model
For objects connected to a model using transmeta you will need an additional field to determine the language, say CharField with "en", "de", "ru" etc.
These were major drawbacks that made me rethink the approach and switch to another solution: django.contrib.sites. Every model that needs internationalization inherits from a SiteModel:
class SiteModel(models.Model):
site = models.ForeignKey(Site)
Every object that would need transmeta translation is connected to a site. Every connected object can determine its language from the parent object's site attribute.
I basically ran the wikipedia approach and had a Site object for every language on a subdomain (en., de., ru.). For every site I started a server instance that had a custom settings file which would set the SITE_ID and the language of the site. I used django.contrib.sites.managers.CurrentSiteManagerto display only the items in the language of the current site. I also had a manager that would give you objects of every language. I constructed a model that connects objects of the same model from different languages denoting that they are semantically the same (think languages left column on wikipedia). The sites all use the same database and share the same untranslated User model, so users can switch between languages without any problem.
Advantages:
Your database schema doesn't need to change for additional languages
You are flexible: add languages easily, have objects in one language only etc.
Works with (generic) foreign keys, they connect to an object and know what language it is. You can display the comments of an object and they will be in one language. This solves your problem.
Disadvantages:
It's a greater deal to setup: you need a django server instance for every site and some more glue code
If you need e.g an article in different languages, you need another model to connect them
You may not need the django Site model and could implement something that does the same without the need of multiple django server instances.
I don't know what you are trying to build and what I described might not fit to your case, but it worked out perfectly for my project (internationalized community platform built upon pinax: http://www.bpmn-community.org/ ). So if you disclose some more about your project, I might be able to advise an approach.
To finally answer your question: No, the generic comments will not work out of the box with transmeta. As you realised you will have to display comments in both languages for the article that is displayed in one language. Or you will have to hack into the comments and change the model and do other dirty stuff (not recommended). The approach I described works with comments and any other pluggable app.
To answer your questions:
Two Django instances can share one database, no problem there.
If you don't want two Django instances, but one, you will have to do the following: A middleware checks the incoming request, extracts desired language from URL (en.example.com or example.com/en/ etc.) and saves the language preference in the request object. The view will have to take the request object with the language and take care of the filtering of objects accordingly. Since there is no dedicated server for the language (like in the sites approach where the language is stored in the settings.py file), you can only get the language from the request and you will have to pass attributes from the request object to Model managers to filter objects.
You could try to fake a global language state in the django application with an approach like threadlocals middleware, however I don't know if this plays out nicely with django I18N engine (which is also does some thread magic).
If you want to go big with your site in multiple languages, I recommend going for the sites-approach.