Поиск по товарным знакам. Поиск по классам.

master
Alexander Kondratyev 9 years ago
parent 37c937bab0
commit 604ad98069
  1. 4
      trademark/lib/poiskznakov.py
  2. 15
      trademark/migrations/0001_initial.py
  3. 98
      trademark/models.py
  4. 19
      trademark/static/trademark/js/form.js
  5. 18
      trademark/static/trademark/js/modal.js
  6. 25
      trademark/static/trademark/less/result.less
  7. 4
      trademark/templates/trademark/form.html
  8. 10
      trademark/templates/trademark/modal.html
  9. 15
      trademark/templates/trademark/nice_block_busy.html
  10. 17
      trademark/templates/trademark/search_detail.html
  11. 2
      trademark/templates/trademark/trademark_detail.html
  12. 0
      trademark/templatetags/__init__.py
  13. 8
      trademark/templatetags/dict.py
  14. 65
      trademark/views.py

@ -24,9 +24,10 @@ class TrademarkSearchAPI():
response = urllib2.urlopen(api_request)
data = json.load(response)
return data
def search_trademark(self, keyword, similarity=100):
def search_trademark(self, keyword, similarity=100, nices=''):
request = {
'module': 'search',
'procedure': 'make_search',
@ -35,6 +36,7 @@ class TrademarkSearchAPI():
'databases': [21, 23],
'use_translit': 'true',
'skip_expired': 'true',
'icgs': [int(nice) for nice in nices.split(',')]
}
if similarity < 100:

@ -15,6 +15,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('request', models.CharField(max_length=200)),
('nices', models.CharField(max_length=200)),
('slug', models.CharField(max_length=200)),
('status', models.IntegerField(default=0)),
('loaded', models.IntegerField(default=0)),
@ -34,6 +35,7 @@ class Migration(migrations.Migration):
('description', models.TextField()),
],
options={
'ordering': ('nice_id',),
'verbose_name': 'nice',
'verbose_name_plural': 'classes',
},
@ -59,9 +61,10 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('title', models.TextField()),
('nice', models.ForeignKey(to='trademark.Nice')),
('nice_id', models.IntegerField()),
],
options={
'ordering': ('nice_id',),
'verbose_name': 'product',
'verbose_name_plural': 'products',
},
@ -99,11 +102,11 @@ class Migration(migrations.Migration):
name='Trademark',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('title', models.CharField(max_length=255)),
('title', models.CharField(max_length=255, null=True)),
('ext_id', models.CharField(unique=True, max_length=20)),
('application_id', models.IntegerField()),
('cert_id', models.IntegerField()),
('owner', models.TextField()),
('application_id', models.CharField(max_length=12, null=True)),
('cert_id', models.CharField(max_length=12, null=True)),
('owner', models.TextField(null=True)),
('image_url', models.URLField(null=True)),
('status', models.CharField(max_length=20)),
('source_url', models.URLField(null=True)),
@ -112,7 +115,7 @@ class Migration(migrations.Migration):
('expiration_at', models.DateField(null=True)),
('renewed_at', models.DateField(null=True)),
('priority_at', models.DateField(null=True)),
('access_key', models.CharField(max_length=20)),
('access_key', models.CharField(max_length=20, null=True)),
('nices', models.ManyToManyField(to='trademark.Nice')),
('products', models.ManyToManyField(to='trademark.Product')),
],

@ -9,6 +9,9 @@ from lib.poiskznakov import TrademarkSearchAPI
from unidecode import unidecode
from django.template.defaultfilters import slugify
from datetime import date
from datetime import timedelta
# from .cms_appconfig import TrademarkConfig
TrademarkAPI = TrademarkSearchAPI()
@ -49,12 +52,12 @@ class Nice(models.Model):
class Product(models.Model):
title = models.TextField()
nice = models.ForeignKey(Nice)
nice_id = models.IntegerField()
class Meta:
verbose_name = _('product')
verbose_name_plural = _('products')
ordering = ('nice__nice_id', )
ordering = ('nice_id', )
def __unicode__(self): # Python 3: def __str__(self):
return self.title
@ -62,37 +65,6 @@ class Product(models.Model):
def __str__(self):
return self.title
@property
def cap_title(self):
line = self.title.strip().replace('[', '(').replace(']', ')')
if line[-1] == ".":
cap_line = line[0].upper() + line[1:-1]
else:
cap_line = line[0].upper() + line[1:]
return cap_line
@property
def titles(self):
titles = self.title.split(';')
try:
if len(titles) > 1:
capitalized = []
for line in titles:
line = line.strip().replace('[', '(').replace(']', ')')
if line[-1] == ".":
cap_line = line[0].upper() + line[1:-1]
else:
cap_line = line[0].upper() + line[1:]
capitalized.append(cap_line)
return capitalized
else:
return []
except:
return []
class Trademark(models.Model):
title = models.CharField(max_length=255, null=True)
@ -127,6 +99,7 @@ class Trademark(models.Model):
class Keyword(models.Model):
request = models.CharField(max_length=200)
nices = models.CharField(max_length=200)
slug = models.CharField(max_length=200)
status = models.IntegerField(default=0)
loaded = models.IntegerField(default=0)
@ -141,6 +114,12 @@ class Keyword(models.Model):
def __str__(self):
return self.request
@property
def nice_objects(self):
nices = self.nices.split(',')
return Nice.objects.filter(nice_id__in=nices)
@property
def contains_results(self):
search = self.searches.filter(similarity=100)[0]
@ -160,7 +139,7 @@ class Keyword(models.Model):
def load_results(self):
for search in self.searches.all():
if search.status != "finished":
if search.status != "finished" or date.today() > search.loaded_at + timedelta(days=30):
search.get_results()
if len(self.searches.all()) == len(self.searches.filter(status="finished")):
@ -194,12 +173,48 @@ class Search(models.Model):
return nices
def send_request(self):
data = TrademarkAPI.search_trademark(keyword=self.keyword.request, similarity=self.similarity)
data = TrademarkAPI.search_trademark(keyword=self.keyword.request, similarity=self.similarity, nices=self.keyword.nices)
self.search_id = data['search_id']
self.save()
def parse_products(self, nice_id, nice_description):
if len(nice_description) == 0:
return
if nice_description[0:1].isdigit():
nice_description = nice_description[nice_description.find('-') + 1:].strip()
titles = nice_description.split(';')
if len(titles) == 1:
try:
titles = nice_description.split(',')
except:
print nice_description
if len(titles) > 0:
products = []
for line in titles:
if len(line.strip()) == 0:
continue
line = line.strip().replace('[', '(').replace(']', ')')
if line[-1] == ".":
line = line[0].upper() + line[1:-1]
else:
line = line[0].upper() + line[1:]
line = line.replace('\n', ' ')
line = ' '.join(line.split())
product, created = Product.objects.get_or_create(nice_id=nice_id, title=line)
products.append(product)
return products
def get_results(self):
results, status = TrademarkAPI.get_results(self.search_id)
@ -249,7 +264,7 @@ class Search(models.Model):
instance.save()
for nice_id in trademark['icgs']:
for nice_id in trademark.get('icgs', []):
nice, created = Nice.objects.get_or_create(nice_id=nice_id)
instance.nices.add(nice)
@ -269,15 +284,16 @@ class Search(models.Model):
instance.expiration_at = trademark.get('dateexp', '')
instance.renewed_at = trademark.get('renewed', '')
for nice_id, nice_description in trademark['icgs'].iteritems():
if nice_description[0:1].isdigit():
nice_description = nice_description[nice_description.find('-') + 1:].strip()
for nice_id, nice_description in trademark.get('icgs', {}).iteritems():
nice_obj, created = Nice.objects.get_or_create(nice_id=nice_id)
product, created = Product.objects.get_or_create(nice=nice_obj, title=nice_description)
instance.products.add(product)
products = self.parse_products(nice_id, nice_description)
instance.products.add(*products)
instance.save()
self.loaded_at = date.today()
self.status = 'finished'
self.save()

@ -60,17 +60,12 @@ TrademarkSearchForm = (function(searchContainer){
if(show_link && iteration > 5) {
var href = ''
$wait.html('<a href="' + tm_url + '">Остановить поиск и перейти к результатам</a>');
} else {
}
if((completed || almost_completed) && advanced_form_scope.opened == false) {
document.location.href = tm_url + "#?nices=" + advanced_form_scope.classes_values.join(',');
if((completed || almost_completed)) {
document.location.href = tm_url;
} else {
if (completed || almost_completed) {
advanced_form_scope.tm_url = tm_url;
}
iteration += 1;
setTimeout(function () {
get_status(slug);
@ -98,7 +93,10 @@ TrademarkSearchForm = (function(searchContainer){
$sending.show();
$.post("/ru/trademarks/online-search/request/",
{ 'keyword': request}).done(function(data) {
{
'keyword': request,
'nices': advanced_form_scope.classes_values.join(',')
}).done(function(data) {
var tm_count = Math.floor(Math.random() * (3000000 - 1000000) + 1000000);
$(searchContainer + ' .trademark-search-count-number').text(tm_count.toLocaleString() + ' знаков')
$advanced_search.show();
@ -133,6 +131,11 @@ TrademarkSearchForm = (function(searchContainer){
}
});
$(searchContainer + ' .trademark-search-submit').click(function(){
if (advanced_form_scope.classes_values != '') {
send();
} else {
advanced_form_scope.callback = send;
advanced_form_scope.open();
}
});
});

@ -8,6 +8,7 @@ angular.module('zuykov')
$scope.classes = $scope.classes_values.length;
$scope.animationsEnabled = true;
$scope.opened = false;
$scope.callback = false;
$scope.open = function (form_id) {
@ -26,26 +27,15 @@ angular.module('zuykov')
$scope.classes_values = classes_values;
$scope.classes = $scope.classes_values.length;
console.log($scope.classes_values, $scope.classes);
$scope.opened = false;
if (typeof(searchResults) != "undefined") {
$.urlParamUpdate('nices', $scope.classes_values.join(','));
searchResults.expand();
}
if (typeof(searchResults) == 'undefined' && $scope.tm_url != false) {
document.location.href = $scope.tm_url + "#?nices=" + $scope.classes_values.join(',');
if ($scope.callback) {
$scope.callback();
}
console.log('load');
}, function () {
$scope.opened = false;
console.log('cancle');
if (typeof(searchResults) == 'undefined' && $scope.tm_url != false) {
document.location.href = $scope.tm_url + "#?nices=" + $scope.classes_values.join(',');
}
});
};

@ -2,10 +2,31 @@
h2 {
margin-top: 0;
}
.trademark-search-advanced-btn {
top: -32px !important;
}
}
.trademark-search {
.trademark-search-form {
margin-bottom: 5px;
.trademark-search-advanced-btn {
position: relative;
z-index: 100;
right: 80px;
top: -37px;
float: right;
}
.trademark-search-advanced-count {
font-size: 12px;
margin-top: 4px;
}
.nice-selected {
margin-bottom: 5px;
}
}
.trademark-search-field {
@ -170,6 +191,10 @@
.trademark-register-block {
background-color: #E8EEFC;
.btn {
margin-right: 5px;
}
}

@ -7,6 +7,7 @@
<button class="btn btn-primary trademark-search-submit" type="button">Найти</button>
</span>
</div>
{% include 'trademark/modal.html' with mode='form' %}
<example>Например, <a class="trademark-search-example" href="#">Coca-Cola</a></example>
</div>
<div class="trademark-search-loading">
@ -19,9 +20,6 @@
<div class="rect4"></div>
<div class="rect5"></div>
</div>
{% include 'trademark/modal.html' with mode='form' %}
</div>

@ -69,20 +69,18 @@
</div>
</script>
<button class="btn btn-default btn-xs trademark-search-advanced-btn" ng-click="open();" value="">Выбрать классы</button>{% if mode != 'form' %} — чтобы уточнить классы МКТУ, регистрацию в которых хотите проверить. {% endif %}
{% verbatim %}
<div>
<p>Поиск происходит {{ classes == 0 ? 'во всех классах' : 'в ' + classes + GetNoun(classes, ' классе', ' классах', ' классах') }}</p>
<p class="trademark-search-advanced-count">Поиск происходит {{ classes == 0 ? 'во всех классах' : 'в ' + classes + GetNoun(classes, ' классе', ' классах', ' классах') }}</p>
<ul class="nice-selected list-unstyled list-inline">
<li ng-repeat="id in classes_values"><span class="label label-default"><strong>{{ nice[id-1].id }}</strong> – {{ nice[id-1].title }}</span></li>
</ul>
</div>
{% endverbatim %}
<div>
<button class="btn btn-primary btn-xs" ng-click="open();" value="">Расширенный поиск</button>{% if mode != 'form' %} — чтобы уточнить классы МКТУ, регистрацию в которых хотите проверить. {% endif %}
</div>
</div>

@ -1,15 +1,20 @@
{% load dict %}
<div class="trademark-search-nice-busy">
<h2>«{{ keyword|title }}» был зарегистрирован в следующих классах</h2>
<ul class="list-unstyled load-more-results" list-type="nices">
{% for product in products_busy %}
{% if product.titles %}
<li class="trademark-search-nice-busy-product load-more-result c{{ product.nice.nice_id }}"><button class="btn btn-xs btn-default" popover="{% if product.nice.description %}{{ product.nice.description }}{% else %}{{ product.nice.title }}{% endif %}" popover-title="{{ product.nice.title }}" popover-trigger="mouseenter" popover-placement="bottom">{{ product.nice.nice_id }} класс</button> <button class="btn btn-xs btn-default trademark-search-show-products" product-id="{{ product.id }}">{{ product.titles|length }} категорий <span class="caret"> </span></button> {{ product.nice.title }}</li>
<ul class="trademark-search-nice-busy-products row" style="display: none;" product-id="{{ product.id }}">{% for title in product.titles %}<li class="col-xs-6">{{ title }}</li>{% endfor %}</ul>
{% for nice in nice_busy %}
{% if products_busy|getitem:nice.nice_id|length > 1 %}
<li class="trademark-search-nice-busy-product load-more-result c{{ nice.nice_id }}"><button class="btn btn-xs btn-default" popover="{% if nice.description %}{{ nice.description }}{% else %}{{ nice.title }}{% endif %}" popover-title="{{ nice.title }}" popover-trigger="mouseenter" popover-placement="bottom">{{ nice.nice_id }} класс</button> <button class="btn btn-xs btn-default trademark-search-show-products" product-id="{{ nice.nice_id }}">{{ products_busy|getitem:nice.nice_id|length }} категорий <span class="caret"> </span></button> {{ nice.title }}</li>
<ul class="trademark-search-nice-busy-products row" style="display: none;" product-id="{{ nice.nice_id }}">{% for product in products_busy|getitem:nice.nice_id %}<li class="col-xs-6">{{ product.title }}</li>{% endfor %}</ul>
{% else %}
<li class="trademark-search-nice-busy-product load-more-result"><button class="btn btn-xs btn-default" popover="{% if product.nice.description %}{{ product.nice.description }}{% else %}{{ product.nice.title }}{% endif %}" popover-title="{{ product.nice.title }}" popover-trigger="mouseenter" popover-placement="bottom">{{ product.nice.nice_id }} класс</button> {{ product.cap_title }}</li>
<li class="trademark-search-nice-busy-product load-more-result"><button class="btn btn-xs btn-default" popover="{% if nice.description %}{{ nice.description }}{% else %}{{ nice.title }}{% endif %}" popover-title="{{ nice.title }}" popover-trigger="mouseenter" popover-placement="bottom">{{ nice.nice_id }} класс</button> {{ products_busy|getitem:nice.nice_id|first }}</li>
{% endif %}
{% endfor %}
<li class="load-more-li">
<button class="btn btn-default load-more">Показать ещё</button> — осталось <span class="load-more-count"></span>
</li>

@ -7,15 +7,16 @@
{% block trademark_content %}
{% include 'trademark/breadcrumb.html' with keyword=keyword.request %}
<h1>Результаты поиска знаков по запросу «{{ keyword|title }}»</h1>
{% include 'trademark/modal.html' %}
<h1>Результаты поиска знаков по запросу «{{ keyword|title }}» в {{ keyword.nice_objects|length }} классах МКТУ</h1>
<p>Поиск происходил в следуюших классах:</p>
<ul class="nice-selected list-unstyled list-inline">
{% for nice in keyword.nice_objects %}
<li><span class="label label-default"><strong>{{ nice.nice_id }}</strong> — {{ nice.title }}</span></li>
{% endfor %}
</ul>
<div class="row">
<div class="col-xs-12 col-sm-8">
<div class="trademark-search-results-null">
<h2>Товарный знак «{{ keyword.request|title }}» не зарегистрирован в выбранных классах</nobr> товаров и услуг</h2>
<button class="btn btn-default btn-xs trademark-search-flush-filter">Показать знаки по всем классам</button>
</div>
{% if identity.count > 0 %}
<ul class="trademark-search-results load-more-results list-inline list-unstyled">
<li class="trademark-search-results-detail">
@ -80,7 +81,7 @@
{% endif %}
{% else %}
<h2>Товарный знак «{{ keyword.request|title }}» не зарегистрирован в базе свидетельств Роспатента</h2>
<h2>Товарный знак «{{ keyword.request|title }}» не зарегистрирован в базе свидетельств Роспатента {% if keyword.nice_objects|length > 0 %}в выбранных классах{% endif %}</h2>
<p>
Существует ряд законодательных требований, которым должен соответствовать знак, не выполнение которых может привести к отказу в регистрации вашего знака.</p>
<p>

@ -54,7 +54,7 @@
</div>
{% include 'trademark/nice_block_busy.html' with keyword=tm.title nice_busy=tm.nices.all products_busy=tm.products.all %}
{% include 'trademark/nice_block_busy.html' with keyword=tm.title nice_busy=tm.nices.all products_busy=products_busy %}
<h4>Источник: Федеральная Cлужба по Интеллектуальной Собственности</h4>
<small><a href="{{ tm.source_url }}" target="blank">{{ tm.source_url }}</a></small>

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
from django import template
register = template.Library()
@register.filter
def getitem ( item, string ):
return item.get(string,'')

@ -35,17 +35,22 @@ class SearchDetailView(generic.DetailView):
contains = self.get_object().searches.filter(similarity=100)[0]
contains_results = contains.results.filter(title__isnull=False, status='Acting').exclude(id__in=identity_ids)
contains_expired_results = contains.results.filter(title__isnull=False, status='Expired').exclude(id__in=identity_ids)
context['contains'] = contains_results[:30]
context['contains'] = contains_results[:18]
contains_ids = contains_results.values_list('id', flat=True)
similar = self.get_object().searches.filter(similarity=97)[0]
similar_results = similar.results.filter(status='Acting').exclude(id__in=contains_ids | identity_ids)
similar_expired_results = similar.results.filter(status='Expired').exclude(id__in=contains_ids | identity_ids)
context['similar'] = similar_results[:30]
context['similar'] = similar_results[:12]
context['similar_expired'] = (contains_expired_results | similar_expired_results).distinct()
context['nice_busy'] = Nice.objects.filter(nice_id__in=nice_busy_ids).order_by('nice_id')
context['products_busy'] = Product.objects.filter(id__in=identity_results.values_list('products__id')).order_by('nice__nice_id')
context['products_busy'] = {}
for nice in context['nice_busy']:
products = Product.objects.filter(id__in=identity_results.values_list('products__id'), nice_id=nice.nice_id)
context['products_busy'][nice.nice_id] = products
context['nice_available'] = Nice.objects.filter(nice_id__in=[x for x in range(1,46) if x not in nice_busy_ids]).order_by('nice_id')
return context
@ -63,22 +68,11 @@ class TrademarkDetailView(generic.DetailView):
tm = self.get_object()
context['tm'] = tm
context['nice_available'] = Nice.objects.filter(nice_id__in=[x for x in range(1,46) if x not in tm.nices.values_list('nice_id', flat=True)]).order_by('nice_id')
# identity = self.get_object().searches.filter(similarity=146)[0]
# identity_results = identity.results.all()
# context['identity'] = identity_results
# identity_ids = identity_results.values_list('id', flat=True)
# nice_busy_ids = identity_results.values_list('nices__nice_id', flat=True).distinct()
# contains = self.get_object().searches.filter(similarity=100)[0]
# contains_results = contains.results.filter(title__isnull=False).exclude(id__in=identity_ids)
# context['contains'] = contains_results[:30]
# contains_ids = contains_results.values_list('id', flat=True)
# similar = self.get_object().searches.filter(similarity=97)[0]
# context['similar'] = similar.results.all().exclude(id__in=contains_ids | identity_ids)[:30]
# context['nice_busy'] = Nice.objects.filter(nice_id__in=nice_busy_ids).order_by('nice_id')
# context['products_busy'] = Product.objects.filter(id__in=identity_results.values_list('products__id')).order_by('nice__nice_id')
context['products_busy'] = {}
for nice in tm.nices.all():
products = Product.objects.filter(id__in=tm.products.values_list('id'), nice_id=nice.nice_id)
context['products_busy'][nice.nice_id] = products
return context
@ -142,43 +136,12 @@ class Search(generic.View):
return HttpResponse(json.dumps(response), content_type='application/json')
try:
identity = keyword.searches.filter(similarity=146)[0]
contains = keyword.searches.filter(similarity=100)[0]
similar = keyword.searches.filter(similarity=97)[0]
response = {
'identity': {
'id': identity.id,
'status': identity.status,
'nices': identity.nices,
'count': identity.results.all().count()
},
'contains': {
'id': contains.id,
'status': contains.status,
'count': contains.results.all().count()
},
'similar': {
'id': similar.id,
'status': similar.status,
'count': similar.results.all().count()
},
'status': 'ok'
}
return HttpResponse(json.dumps(response), content_type='application/json')
except:
return HttpResponse(json.dumps({ 'status': 'error', 'description': 'Request not found', 'slug': slug }), content_type="application/json")
def post(self, request):
keyword = request.POST.get('keyword', '')
nices = request.POST.get('nices', '')
if keyword:
k, created = Keyword.objects.get_or_create(request=keyword)
k, created = Keyword.objects.get_or_create(request=keyword, nices=nices)
else:
return HttpResponse(json.dumps({ 'status': 'error', 'description': 'Empty request'}), content_type="application/json")

Loading…
Cancel
Save