Django 1.7 multisite User model

2024/11/17 20:27:19

I want to serve a Django application that serves multiple web sites by single database but different user sets. Think like a blog application, it will be used by several domains with different themes, but use same database by adding a site field to models.

I use Django's SitesFramework for that job. But the problem is, I couldn't separate user models for different sites. I want to use same user model with a site field and email field that unique per site.

I tried to extend AbstractUser model like that:

from django.contrib.auth.models import AbstractUser
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManagerclass Member(AbstractUser):username = Nonesite = models.ForeignKey(Site)USERNAME_FIELD = 'email'REQUIRED_FIELDS = []on_site = CurrentSiteManager()class Meta:unique_together = ('site', 'email')

But gives that error: 'Member.email' must be unique because it is named as the 'USERNAME_FIELD'.

What is the best practice for that issue?

Answer

I hope this approach helps to you:

1) Compose username before save:

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManagerclass Member(AbstractUser):site = models.ForeignKey(Site)on_site = CurrentSiteManager()USERNAME_FIELD = 'username'REQUIRED_FIELDS = []class Meta:unique_together = ('site', 'email')from django.db.models.signals import pre_save
from django.dispatch import receiver@receiver(pre_save, sender=Member)
def compose_username(sender, instance, **kwargs):instance.username = "{0}__{1}".format( instance.email, instance.site_id ) 

2) Then overwrite ModelBackend in your custom auth backend:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_modelclass MyModelBackend(ModelBackend):def authenticate(self, username=None, password=None, **kwargs):UserModel = get_user_model()site = kwargs.get('site')identifier = "{0}__{1}".format( username, site )try:user = UserModel.objects.get(username=identifier)if user.check_password(password):return userexcept UserModel.DoesNotExist:# Run the default password hasher once to reduce the timing# difference between an existing and a non-existing user (#20760).UserModel().set_password(password)

3) Remember set your custom backend on settings:

AUTH_USER_MODEL='s1.Member'
SITE_ID = 1
AUTHENTICATION_BACKENDS = ( 'MyApp.MyModule.MyModelBackend',)

4) Include site when authenticate:

>>> from s1.models import Member as M
>>> m1 = M()
>>> m1.site_id = 1
>>> m1.email = '[email protected]'
>>> m1.save()
>>> m1.set_password('hi')
>>> m1.save()
>>> 
>>> from django.contrib.auth import authenticate, login
>>> u=authenticate(username='[email protected]', password='hi', site=1)
>>> u
<Member: [email protected]_at_1>
>>> 
https://en.xdnf.cn/q/71143.html

Related Q&A

Does for key in dict in python always iterate in a fixed order?

Does the python codefor key in dict:..., where dict is a dict data type, always iterate in a fixed order with regrard to key? For example, suppose dict={"aaa":1,"bbb",2}, will the …

Kinesis Firehose lambda transformation

I have the following lambda function as part of Kinesis firehose record transformation which transforms msgpack record from the kinesis input stream to json.Lambda Runtime: python 3.6from __future__ im…

Python: find out whether a list of integers is coherent

I am trying to find out whether a list of integers is coherent or at one stretch, meaning that the difference between two neighboring elements must be exactly one and that the numbers must be increasin…

Create resizable/multiline Tkinter/ttk Labels with word wrap

Is it possible to create a multi-line label with word wrap that resizes in sync with the width of its parent? In other words the wordwrap behavior of Notepad as you change the width of the NotePad win…

Unicode, regular expressions and PyPy

I wrote a program to add (limited) unicode support to Python regexes, and while its working fine on CPython 2.5.2 its not working on PyPy (1.5.0-alpha0 1.8.0, implementing Python 2.7.1 2.7.2), both run…

Python str object has no attribute read

Python 3.3.2 import json & urllib.requestJson[{"link":"www.google.com","orderid":"100000222"}, {"link":"www.google.com","orderid&quo…

Efficient upsert of pandas dataframe to MS SQL Server using pyodbc

Im trying to upsert a pandas dataframe to a MS SQL Server using pyodbc. Ive used a similar approach before to do straight inserts, but the solution Ive tried this time is incredibly slow. Is there a mo…

Comparison on the basis of min function

How exactly does the min function work for lists in python ?For example,num = [1,2,3,4,[1,2,3]]num2 = [1,2,3,4,5]min(num,num2) gives num2 as the result. Is the comparison value based or length based ?

Python Pandas rolling aggregate a column of lists

I have a simple dataframe df with a column of lists lists. I would like to generate an additional column based on lists.The df looks like:import pandas as pd lists={1:[[1]],2:[[1,2,3]],3:[[2,9,7,9]],4:…

Easy way of overriding default methods in custom Python classes?

I have a class called Cell:class Cell:def __init__(self, value, color, size):self._value = valueself._color = colorself._size = size# and other methods...Cell._value will store a string, integer, etc. …