Skip to content

Commit

Permalink
fix: refactor code for "add instrument name"
Browse files Browse the repository at this point in the history
- remove "alias" field from "InstrumentName" model;
- move "publish_name" to a separate .py file
- use "csrf_protect" decorator for "publish_name"
- extract the common code in "mansonryView.html" and "stdView.html"

Refs: #163
  • Loading branch information
kunfang98927 committed Oct 21, 2024
1 parent 888e84b commit 8079346
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 228 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,23 @@ def create_database_objects(
instrument = Instrument.objects.create(**instrument_attrs)
for lang, name in ins_names.items():
description = ins_descs.get(lang, "")
alias = ins_alias.get(lang, [])
# Create InstrumentName object for "name" in "lang" with "description"
InstrumentName.objects.create(
instrument=instrument,
language=self.language_map[lang],
description=description,
alias=", ".join(alias),
name=name,
source_name="Wikidata",
)
alias = ins_alias.get(lang, [])
# Create InstrumentName object for "alias" in language "lang"
for alias_name in alias:
InstrumentName.objects.create(
instrument=instrument,
language=self.language_map[lang],
name=alias_name,
source_name="Wikidata",
)
img_obj = AVResource.objects.create(
instrument=instrument,
type="image",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.2.5 on 2024-10-04 15:30
# Generated by Django 4.2.5 on 2024-10-21 15:05

from django.db import migrations, models

Expand All @@ -9,13 +9,6 @@ class Migration(migrations.Migration):
]

operations = [
migrations.AddField(
model_name="instrumentname",
name="alias",
field=models.CharField(
blank=True, help_text="Alternative name for the instrument"
),
),
migrations.AddField(
model_name="instrumentname",
name="description",
Expand Down
3 changes: 0 additions & 3 deletions web-app/django/VIM/apps/instruments/models/instrument_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,3 @@ class InstrumentName(models.Model):
description = models.CharField(
blank=True, help_text="Description of the instrument name"
) # Stand-in for description
alias = models.CharField(
blank=True, help_text="Alternative name for the instrument"
) # Stand-in for alias
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% load static %}

<div class="instrument-img-container">
<img src="{% static instrument.thumbnail.url %}" class="card-img-top rounded p-2 img-fluid instrument-img" alt="instrument thumbnail" onerror="this.onerror=null;this.src='{% static "instruments/images/no-image.svg" %}';" />
<div class="middle-button-group">
{% if user.is_authenticated %}
<button type="button"
class="btn"
data-bs-toggle="modal"
data-bs-target="#addNameModal"
data-instrument-name="{{ instrument.instrumentname_set.first.name|title }}"
data-instrument-wikidata-id="{{ instrument.wikidata_id }}">
Add instrument name
</button>
<button type="button"
class="btn"
data-bs-toggle="modal"
data-bs-target="#uploadImagesModal"
data-instrument-name="{{ instrument.instrumentname_set.first.name|title }}"
data-instrument-wikidata-id="{{ instrument.wikidata_id }}">
Upload new images
</button>
{% endif %}
<a class="btn"
href="https://www.wikidata.org/wiki/{{ instrument.wikidata_id }}"
target="_blank">View on Wikidata</a>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,11 @@
<div class="col">
<div class="text-decoration-none">
<div class="card mb-3">
<div class="instrument-img-container">
<img src="{% static instrument.thumbnail.url %}" class="card-img-top rounded p-2 instrument-img" alt="instrument thumbnail" onerror="this.onerror=null;this.src='{% static "instruments/images/no-image.svg" %}';" />
<div class="middle-button-group">
{% if user.is_authenticated %}
<button type="button"
class="btn"
data-bs-toggle="modal"
data-bs-target="#addNameModal"
data-instrument-name="{{ instrument.instrumentname_set.first.name|title }}"
data-instrument-wikidata-id="{{ instrument.wikidata_id }}">
Add instrument name
</button>
<button type="button"
class="btn"
data-bs-toggle="modal"
data-bs-target="#uploadImagesModal"
data-instrument-name="{{ instrument.instrumentname_set.first.name|title }}"
data-instrument-wikidata-id="{{ instrument.wikidata_id }}">
Upload new images
</button>
{% endif %}
<a class="btn"
href="https://www.wikidata.org/wiki/{{ instrument.wikidata_id }}"
target="_blank">View on Wikidata</a>
</div>
</div>
{% include "instruments/includes/instrumentContainer.html" %}

<div class="card-body pb-0 pt-0">
<p class="card-title text-center notranslate ">
{% for instrumentname in instrument.instrumentname_set.all %}
{{ instrumentname.name|title }}
{% endfor %}
{{ instrument.instrumentname_set.all.first.name|title }}
</p>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,12 @@
<div class="text-decoration-none">
<div class="card mb-3">
<div class="square-box">
<div class="instrument-img-container">
<img src="{% static instrument.thumbnail.url %}" class="card-img-top rounded p-2 img-fluid instrument-img" alt="instrument thumbnail" onerror="this.onerror=null;this.src='{% static "instruments/images/no-image.svg" %}';" />
<div class="middle-button-group">
{% if user.is_authenticated %}
<button type="button"
class="btn"
data-bs-toggle="modal"
data-bs-target="#addNameModal"
data-instrument-name="{{ instrument.instrumentname_set.first.name|title }}"
data-instrument-wikidata-id="{{ instrument.wikidata_id }}">
Add instrument name
</button>
<button type="button"
class="btn"
data-bs-toggle="modal"
data-bs-target="#uploadImagesModal"
data-instrument-name="{{ instrument.instrumentname_set.first.name|title }}"
data-instrument-wikidata-id="{{ instrument.wikidata_id }}">
Upload new images
</button>
{% endif %}
<a class="btn"
href="https://www.wikidata.org/wiki/{{ instrument.wikidata_id }}"
target="_blank">View on Wikidata</a>
</div>
</div>
{% include "instruments/includes/instrumentContainer.html" %}

</div>
<div class="card-body pb-0 pt-0">
<p class="card-title text-center notranslate">
{% for instrumentname in instrument.instrumentname_set.all %}
{{ instrumentname.name|title }}
{% endfor %}
{{ instrument.instrumentname_set.all.first.name|title }}
</p>
</div>
</div>
Expand Down
153 changes: 0 additions & 153 deletions web-app/django/VIM/apps/instruments/views/instrument_list.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
""" Django views for the instrument list page. """

import json
from django.db.models import Prefetch
from django.db.models.query import QuerySet
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import ListView
from django.http import JsonResponse
import requests
from VIM.apps.instruments.models import Instrument, Language, InstrumentName
from VIM.apps.instruments.views.wiki_apis import (
get_csrf_token,
add_info_to_wikidata_entity,
)


class InstrumentList(ListView):
Expand Down Expand Up @@ -111,149 +104,3 @@ def get_queryset(self) -> QuerySet[Instrument]:
return Instrument.objects.select_related("thumbnail").prefetch_related(
instrumentname_prefetch_manager
)


# Django view to handle publishing to Wikidata
@csrf_exempt
def publish_name(request):
"""
View to publish new instrument names to Wikidata.
This view expects a POST request with the following JSON body like this:
{
"wikidata_id": "Q12345",
"entries": [
{
"language": "en",
"name": "English label",
"source": "Source name",
"description": "Description",
"alias": "Alias"
},
{
"language": "fr",
"name": "French label",
...
}
],
"publish_to_wikidata": true
}
The view will publish the provided entries to the Wikidata entity with the given ID.
Returns:
JsonResponse: JSON response with status and message
"""

if request.method == "POST":
# Parse the JSON request body
data = json.loads(request.body)
username = "YOUR_USERNAME" # Replace with actual username
password = "YOUR_PASSWORD" # Replace with actual credentials
wikidata_id = data.get("wikidata_id")
entries = data.get("entries")
publish_to_wikidata = data.get("publish_to_wikidata", False)

if not wikidata_id or not entries:
return JsonResponse({"status": "error", "message": "Missing required data"})

try:
# Fetch the instrument from the database
instrument = Instrument.objects.get(wikidata_id=wikidata_id)

# Process each entry: save locally, and conditionally publish to Wikidata
if publish_to_wikidata:
csrf_token, lgusername, error_message = get_csrf_token(
username, password
)

# Check if there was an error
if error_message:
return JsonResponse(
{
"status": "error",
"message": f"Failed to get CSRF token: {error_message}",
}
)
for entry in entries:
language_code = entry["language"]
name = entry["name"]
source = entry["source"]
description = entry["description"]
alias = entry["alias"]

# Get the language object
language = Language.objects.get(wikidata_code=language_code)

# Optionally publish to Wikidata
if publish_to_wikidata:
# Publish the new label to Wikidata
response_label = add_info_to_wikidata_entity(
"wbsetlabel",
csrf_token,
wikidata_id,
name,
language_code,
lgusername,
)
if "error" in response_label:
return JsonResponse(
{
"status": "error",
"message": f"Failed to publish label: {response_label}",
}
)

# Publish the new description to Wikidata
response_desc = add_info_to_wikidata_entity(
"wbsetdescription",
csrf_token,
wikidata_id,
description,
language_code,
lgusername,
)
if "error" in response_desc:
return JsonResponse(
{
"status": "error",
"message": f"Failed to publish description: {response_desc}",
}
)

# Publish the new alias to Wikidata
response_alias = add_info_to_wikidata_entity(
"wbsetaliases",
csrf_token,
wikidata_id,
alias,
language_code,
lgusername,
)
if "error" in response_alias:
return JsonResponse(
{
"status": "error",
"message": f"Failed to publish alias: {response_alias}",
}
)

# Save to the local database
InstrumentName.objects.create(
instrument=instrument,
language=language,
name=name,
source_name=source,
description=description,
alias=alias,
)

return JsonResponse(
{
"status": "success",
"message": "Data saved successfully!",
}
)
except Instrument.DoesNotExist:
return JsonResponse({"status": "error", "message": "Instrument not found"})
return JsonResponse({"status": "error", "message": "Invalid request method"})
Loading

0 comments on commit 8079346

Please sign in to comment.