Since I made the app with Django for the first time, it is a memorandum of problems and solutions that I had at that time. This time, I made a ranking site for AtCoder. I had a hard time understanding the big picture of the MVC model (MTV for Django?). Reference (http://mimumimu.net/blog/2011/11/21/python-django-%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F%E3%80 % 82-mtv-model-% E3% 81% AB% E3% 81% A4% E3% 81% 84% E3% 81% A6 /)
What kind of service do you want to create in the first place? ->
$ django-admin startproject project-name
$ cd project-name
$ python manage.py startapp app-name
Writing HTML, CSS, and JavaScript was a hassle, so download the Bootstrap template.
In Django, put HTML in the / project / app / templates folder and CSS, JavaScript in the / project / static / app folder.
HTML file processing:
-Base HTML file-
Write the navigation bar and the file to be read as `{% static'project / app / file'%}`
.
<title>
In the contents{% block title %} {% endblock %}、
<body>
In the contents{% block body %} {% endblock %}write.
-HTML file to extend-
The contents of the HTML file <title>` `` are {% block title%} {% endblock%}, Write the contents of the HTML file
Implement the Model considered in 0.
In this case, the point is that you can log in as your own User instead of the default. models.py (partial excerpt)
from django.contrib.auth.models import (BaseUserManager, AbstractBaseUser)
class UserManager(BaseUserManager):
def create_user(self, username, email, password, **extra_fields):
now = timezone.now()
if not email:
raise ValueError('Users must have an email address.')
email = UserManager.normalize_email(email)
user = self.model(
username=username,
email=email,
is_active=True,
last_login=now,
date_joined=now,
**extra_fields
)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, email, password, **extra_fields):
user = self.create_user(username, email, password)
user.is_active = True
user.is_staff = True
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
username = models.CharField(_('username'), max_length=30, unique=True,)
arc_user_name = models.CharField(_('arc name'), max_length=15, blank=True)
email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
delete = models.BooleanField(default=0)
score = models.IntegerField(default=0)
main_language = models.CharField(max_length=15, default='')
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
def email_user(self, subject, message, from_email=None):
send_mail(subject, message, from_email, [self.email])
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return self.is_admin
def get_short_name(self):
"Returns the short name for the user."
return self.arc_user_name
def __str__(self):
return self.username
--Basically, I wrote it using a class-based general-purpose view. --CreateView for user registration and result posting, TemplateView for others. --By using LoginRequiredMixin, only logged-in users can view it. --If you manage external libraries collectively with atcoder_ranking.commons.libraries, the code will be clean.
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView, CreateView
from atcoder_ranking.commons.libraries import *
from .models import *
class IndexView(LoginRequiredMixin, TemplateView):
template_name = 'index.html'
def get(self, _, *args, **kwargs):
users = User.objects.all()
results = Result.objects.all().select_related('user')
for user in users:
user.score = len(results.filter(user=user)) * 100
language_list = [result.result_language for result in results.filter(user=user)]
if language_list != []:
#Select the most numerous language as the main language
user.main_language = Counter(language_list).most_common(1)[0][0]
user.save()
context = super(IndexView, self).get_context_data(**kwargs)
context['users'] = User.objects.all().order_by('-score')[: 3]
return render(self.request, self.template_name, context)
Create for the created views.py.
from django.conf.urls import url
from django.contrib import admin
import ranking.views as ranking_view
urlpatterns = [
# admin
url(r'^admin/?', admin.site.urls),
# top page
url(r'^$', ranking_view.TopView.as_view()),
# ranking
url(r'^ranking/?$', ranking_view.IndexView.as_view()),
url(r'^ranking/result.png$', ranking_view.plotResults),
url(r'^ranking/create/$', ranking_view.CreateUserView.as_view()),
url(r'^ranking/problems/$', ranking_view.AtCoderProblemsView.as_view()),
url(r'^ranking/get_problems/$', ranking_view.GetProblemsView.as_view()),
url(r'^ranking/posts/$', ranking_view.PostsView.as_view()),
url(r'^ranking/posts/(?P<posts_id>[0-9]+)/$', ranking_view.PostsDetailView.as_view()),
url(r'^ranking/create_posts/$', ranking_view.CreatePostsView.as_view()),
url(r'^ranking/login/$', ranking_view.LoginView.as_view(), name='login'),
url(r'^ranking/logout/$', ranking_view.logout, name='logout')
]
You can write it as it is, or you can use Selenium. I made a test to create a Model object using factory_boy.
factory.py
from atcoder_ranking.commons.libraries import *
from ranking.models import *
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
username = factory.Sequence(lambda n: 'testing_user{}'.format(n))
arc_user_name = factory.Faker('name')
email = factory.Sequence(lambda n: 'testuser{}@gmail.com'.format(n))
password = factory.PostGenerationMethodCall(
'set_password', 'ranking_password')
test.py
class IndexViewTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = UserFactory.create()
def setUp(self):
self.client = ServiceTestTool.login(Client(), IndexViewTest.user, 'ranking_password')
def test_index_ranking(self):
# create 10 testusers
users = [UserFactory.create() for i in range(10)]
# create posts for testusers:
result1 = [ResultFactory.create(user=users[1]) for i in range(30)]
result2 = [ResultFactory.create(user=users[2]) for i in range(20)]
result3 = [ResultFactory.create(user=users[3]) for i in range(40)]
result4 = [ResultFactory.create(user=users[4]) for i in range(10)]
result5 = [ResultFactory.create(user=users[5]) for i in range(5)]
result6 = [ResultFactory.create(user=users[6]) for i in range(50)]
response = self.client.get('/ranking/')
self.assertContains(response, users[1].username)
self.assertContains(response, users[3].username)
self.assertContains(response, users[6].username)
self.assertNotContains(response, users[2].username)
self.assertNotContains(response, users[4].username)
self.assertNotContains(response, users[5].username)
self.assertNotContains(response, users[0].username)
$ python manage.py test
$ python manage.py runserver
If it is displayed like this, it is complete!
Recommended Posts