How to apply DRY to Django Models, forms - django

I'm working on a website and simultaneously on a mobile app.
For the website I've created a Django Form for the User model which override the clean and valid_ methods to provide custom validation.
For the mobile app I'm doing a REST API which exposes and endpoint to create a new user using Tastypie for this.
My doubt is where and how should I define the custom validation for the User model applying the DRY principle.
I can create a UserForm from the data provided by the user in the mobile app, then use the method is_valid() for validating the data, but the form contains a password_confirm field which is also validated and in the app this field doesn't exist.
Should I create a UserForm specific for the mobile app? Should I move these validations to the model class?

The simplest way is probably to subclass the form. Create a LoginForm that does not have the password2 field, and use that one for the mobile login API. Then make a subclass called WebLoginForm and add a password2 field, as well as a clean_password2() method that includes the validation logic. That way, you won't even need to override any of your other clean() code.
An even easier--though hackish--solution would be to have the mobile app submit the password the user wrote both as "password1" and "password2" when it makes the API call.

Related

Django send email from a CBV without having a model

I need to send with Django email when a user completes a contact form.
Because the information, from the form is not kept in Django database, I don't have models for it, just get the information and send email.
I'm using Class Based Views.
I'm thinking of inheriting from View, but where(method) and how I hook my sending email ?
Can I use just inputs(direct html form), or I need to create a Django form ?
You should create a Django form. Then your view can inherit from FormView, and your mail sending functionality would go in form_valid.

The relation between a model and it's form in Django, and user authentication

I'm migrating something from an old PHP/apache server to Django. I'm a bit stumped with the 'ModelForm'.
As far as I understand, a "Model" is the abstraction for persistent elements in my website/server - specifically this is something stored physically, say in a database, and defines the fields (read columns) in the DB.
I started moving the authentication part of the site, and discovered models, and specifically the User model (I made an empty User inheriting AbstractUser just in case I will ever need to extend things). Now I want to create a simple two field form, to authenticate login.
The form:
Username (which is a field of User, by default)
Password (Which is not).
Even the 'Username' needs a redefinition in the model form. So my questions:
What is the advantage of the model form (over just a form)? - seems like you're redefining fields anyway, and obviously sometimes adding fields on top of the model.
Specifically for authentication, I probably need to store my salted hash associated with the user somehow, compare my password using that and retrieve the user object. This is something I find very hard to find in the Django docs - they just have too much written on authentication, and not one full code example. Do I put this in the "validate" method of form, retrieving there an object and storing it in a session or something?
If there is a deeper relation between a model form and the associated model, I would like to know as well.
Simple django forms and modelforms have quite differences.
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter']
The above example illustrates that you don't have to write any form field in here. The model form will itself create a form which is based on the attributes provided in the model ('Article' in this example).
If you create a simple django form then it would be something like:
class ArticleForm(forms.Form):
some_field = forms.CharField(some_attrs)
...
The django User model provides you everything you need for authentication. When you want to create users just import django.contrib.auth.models.User and use create method to create objects. Then when you want to authenticate a user use authenticate method.
from django.contrib.auth import authenticate, login
def user_login(request):
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
# after authentication login the user or set cookies or modify the session or some other action can be taken
return HttpResponse("Some response or use render for html page")
username and password will be coming from your post request.
If you want to extend default Django user model you can use django user model as onetoonefield in your extended model.
class AppUser(models.Model):
user = models.OneToOneField(User)
... # other custom fields

Django custom user model and registration

I have a Django application where I enabled login and registration with Tivix's django-rest-auth (https://github.com/Tivix/django-rest-auth).
Now,
I want to have a custom user model with few additional fields
I want to be able to enable registration along with these additional fields.
Login would be done with email instead of username
What are the steps to achieve this? I went through answers, however I was confused with few things:
The role of serializers here and custom user signUp form and whether I should have a signUp view as well?
Custom user model from AbstractBaseUser or simply Userof django.contrib.auth.models
I already tried to implement something and ran into an issue (django-rest-auth custom registration fails to save extra fields), so wanted to ask for a correct approach.

Django authentication with custom model User

For my needs builtin model User is not enough... So I have my own model UserProfile and I want make authentication on site through this model (UserProfile does not inherit from User model and not related to it at all).
My Model:
class UserProfile(models.Model):
password = models.CharField(max_length = 40)
email = models.EmailField(max_length = 72, unique = True)
## Add this so that you can use request.user.is_authenticated
def is_authenticated(self):
return True
But builtin authentication uses model User.
So I want to understand how can I change that, so authentication use my model UserProfile with all auth features???
A good tutorial would be great!
(Step by step in views, models and authentication)
PS: I know I can store extra data in other model but I don't want that
Here's an even more extreme example but illustrates that what you want to do can be done. The author not only replaces the User model which the authentication backend uses but also uses SQLAlchemy instead of the Django ORM. http://tomforb.es/using-a-custom-sqlalchemy-users-model-with-django
The main point is that you need to write your backend authenticate and get_user methods to retrieve your custom User model. If you want to also support permissions you would need to write has_perm.
I used this article and it worked good enough for me, hope it can be useful for you.
Sultan

Django authentication problem - how can I force active users to setup a profile first?

I've put myself into somewhat of a pickle. I use django-registration often, and it seems to work for most situations. However, I want to require users to build their profile (eg: demographic information) before they can visit any of the other pages.
This is how I desire the current setup to run:
visitor fills out registration form --(submit)--->
user email verification --(link creates active user)--->
--(redirected to profile view)--->
user fills out profile form --(submit)-->
user can now access the rest of the website
Is there a recommended way to do this?
One of the ways of doing it would be to use your own #profile_required decorator rather than the django's built in login_required on all your views.
#login_required
def profile_required(func,request,*args,**kwargs):
has_profile = request.user.profile_set.count()
if not has_profile:
return redirect('create_profile')
return func(request,*args,**kwargs)
Then on each view you want to have a user with profile visit, just:
#profile_required
def my_awesome_view(request):
...