django-phpBB3

Django, Flask, Bottle, WSGI, CGI…
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Die Limitierung Nur alphanumerische Zeichen (Buchstaben, Ziffern und @/./+/-/_) sind erlaubt. kommt von Django, siehe auch: https://docs.djangoproject.com/en/1.4/t ... r.username

Ich vermute mal, es ist außerdem nur in den Forms limitiert:

Code: Alles auswählen

    username = forms.RegexField(label=_("Username"), max_length=30,
        regex=r'^[\w.@+-]+$',
        help_text = _("Required. 30 characters or fewer. Letters, digits and "
                      "@/./+/-/_ only."),
        error_messages = {
            'invalid': _("This value may contain only letters, numbers and "
                         "@/./+/-/_ characters.")})
Somit sollte es leicht möglich sein, mit einer eigenen Form und dem dazu gehörigen views die Limitierung selbst zu gestalten. Aber ich denke nicht das es wirklich Sinnvoll ist.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
lunar

@jens Ich fände es durchaus sinnvoll, wenn ein Benutzer seinen echten Namen ohne Einschränkungen eintippen könnte, also insbesondere auch mit Leerzeichen zwischen Vor- und Nachnamen :) Und ich fände es lustig, wenn Benutzer Unicode-Symbole in ihren Namen verwenden könnten... warum auch nicht? Diese Einschränkung ist doch künstlich, und ich sehe keinen immanenten Grund dazu.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

jens hat geschrieben:Ich vermute mal, es ist außerdem nur in den Forms limitiert:
Siehe dazu auch http://stackoverflow.com/questions/1218 ... -usernames.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Naja, man kann auch ein Display-Name-Feld haben. Username ist E-Mail-Adresse, wie das so häufig im Internet anzutreffen ist und Anzeigename ist dann der entsprechende Nickname.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

/me hat geschrieben:
jens hat geschrieben:Ich vermute mal, es ist außerdem nur in den Forms limitiert:
Siehe dazu auch http://stackoverflow.com/questions/1218 ... -usernames.
Das stimmt:
It is really not a problem - because this character restriction is in UserCreationForm (or RegistrationForm in django-registration) only as I remember, and you can easily make your own since field in database is just normal TextField.
Also eigentlich wird es nur beim User erstellen limitiert, wenn man es mit dem Standard django forms macht.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Bin auf ein neues Problem bei der migration gestoßen. Dank pudb weiß ich jetzt warum:

Hier im Forum konnte man als "Gast" posten. Eines der ersten Threads wurde als Gast anscheinend als Gast gestartet. Komisch ist, wenn man sich: http://www.python-forum.de/viewtopic.php?t=9 ansieht, sind alle User dort noch vorhanden. Doch in der Übersicht: http://www.python-forum.de/viewforum.php?f=5&start=1550 (Letzte Seite von "Offtopic") sieht man in der Spalte Autor "Gast", mit Link zu http://www.python-forum.de/memberlist.p ... rofile&u=7 (Ein User mit ID 7)

In der DB ist topic.poster_id == 7
Allerdings gibt es keinen User mit ID 7... Es gibt eine Lücke zwischen ID 6 und 10

Die Frage ist nun: Ist das nur beim pseudo User "Gast" der Fall, oder gibt es generell "Lücken" wenn man User löscht?

Als work-a-round fällt mir jetzt nur ein, alle nicht existierenden User auf "Anonymous" zu mappen. Das ist ein pseudo User Account von phpBB. (Wobei ich denke das eigentlich Gast == Anonymous sein sollte. Sind anscheinend aber zwei verschiedene Accounts?)

EDIT: So oft kommt es anscheinend nicht vor:

Code: Alles auswählen

 *** Migrate phpBB topic entries...
    get topic watch information...OK
topic 9 poster: phpBB User with ID 7 doesn't exist. Use Anonymous.
topic 54 poster: phpBB User with ID 4 doesn't exist. Use Anonymous.
topic 182 poster: phpBB User with ID 3 doesn't exist. Use Anonymous.
topic 185 poster: phpBB User with ID 3 doesn't exist. Use Anonymous.
topic 188 poster: phpBB User with ID 3 doesn't exist. Use Anonymous.
topic 229 poster: phpBB User with ID 4 doesn't exist. Use Anonymous.
topic 250 poster: phpBB User with ID 4 doesn't exist. Use Anonymous.
topic 291 poster: phpBB User with ID 4 doesn't exist. Use Anonymous.
topic 402 poster: phpBB User with ID 3 doesn't exist. Use Anonymous.
topic 410 poster: phpBB User with ID 4 doesn't exist. Use Anonymous.
topic 1077 poster: phpBB User with ID 4 doesn't exist. Use Anonymous.
topic 8405 poster: phpBB User with ID 3510 doesn't exist. Use Anonymous.
topic 8407 poster: phpBB User with ID 3467 doesn't exist. Use Anonymous.
 *** 27459 topics migrated in 36.0 min (rate: 12.7/sec)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Leonidas hat geschrieben:Naja, man kann auch ein Display-Name-Feld haben. Username ist E-Mail-Adresse, wie das so häufig im Internet anzutreffen ist und Anzeigename ist dann der entsprechende Nickname.
Django 1.5 behebt die Probleme so oder so ;) Siehe: https://github.com/django/django/pull/370 (Teile von Inyoka laufen schon darauf, also funktioniert der Patch auch bereits relativ gut ;))
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das ist gut. Hatte mich eh dazu entschlossen den Usernamen nicht zu verändern.

Nun scheint die Migration auch mit den Dump vom Forum hier zu laufen. Allerdings könnte man sich nochmal ansehen, ob man es noch optimieren kann.

Während die 27.500 topics mit ca. 150/sek in 3Min migriert werden, geht es bei den eigentlichen posts auf dem selben Maschine mit nur mageren 7/sek zu... Bei rund 220.000 Posts dauert das also einige Stunden. Wobei macht man ja nur einmal. Wäre also was für einen "über die nacht" Job.
Kann mir vorstellen, das u.a. das säubern des bbcode eine weile dauert. Außerdem wird jeweils die HTML Version generiert.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Warum dauert das denn so lang? Schon mal den Profiler angeworfen? Ist ja nicht so dass 220.000 Posts jetzt so eine riesige Datenmenge wären, mein DB-Dump in SQLite (ohne diese Cache-Tabellen die phpBB anlegt) ist jetzt nur 68MB groß.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hast du Links für mich zum Thema Profiling? Hab ich bisher noch nie gemacht.

Neue Problem: https://github.com/jedie/django-phpBB3/issues/13
Wegen dem hier: http://www.python-forum.de/viewtopic.php?p=13202#p13202 Dort kommt im code das vor:

Code: Alles auswählen

c->modify = &mymodify;
Also eigentlich ist es &mymodify;

Das ist glaube ich ein Bug in phpBB, siehe auch: http://www.python-forum.de/viewtopic.php?f=10&t=22855

Hab dazu ein work-a-round comittet: https://github.com/jedie/django-phpBB3/ ... 5516be7f34
Weiß allerdings nicht ob das jetzt die Beste Lösung ist.
Man müßte wohl nachsehen, wo ein &bla; vorkommt. Ob es im Text oder im code-Block ist.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Zum Thema Profiling, schau dir doch die Dokumentation das Python-Profilers cProfile an.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Leonidas hat geschrieben:Zum Thema Profiling, schau dir doch die Dokumentation das Python-Profilers cProfile an.
Ja, das mache ich gerade, so:

Code: Alles auswählen

phpBB2DjangoBB_project$ python -m cProfile -s cumulative manage.py phpbb2djangobb --flush_djangobb > stats.txt
Tipps gibt es außerdem hier: http://wiki.python.org/moin/PythonSpeed ... iling_Code

Mal sehen was raus kommt.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Alles ab cumtime > 10 mit einem zusammen-gelöschtem Datensatz:

Code: Alles auswählen

...
 *** 202 topics migrated in 13.0 sec (rate: 15.6/sec) 
...
 *** 1024 posts migrated in 10.0 min (rate: 1.7/sec) 
...
         116963147 function calls (115264047 primitive calls) in 629.339 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000  629.340  629.340 manage.py:2(<module>)
        1    0.000    0.000  629.277  629.277 __init__.py:438(execute_from_command_line)
        1    0.000    0.000  629.277  629.277 __init__.py:340(execute)
        1    0.000    0.000  628.171  628.171 base.py:187(run_from_argv)
        1    0.000    0.000  628.169  628.169 base.py:198(execute)
        1    0.000    0.000  627.116  627.116 phpbb2djangobb.py:99(handle)
        1    0.007    0.007  627.116  627.116 phpbb2djangobb.py:108(_handle)
        1    0.102    0.102  600.181  600.181 phpbb2djangobb.py:554(migrate_posts)
     1225    0.040    0.000  596.343    0.487 manager.py:136(create)
     1225    0.028    0.000  596.142    0.487 query.py:370(create)
     1023    0.039    0.000  591.749    0.578 models.py:219(save)
     1665    0.018    0.000  590.419    0.355 base.py:452(save)
     1665    0.136    0.000  590.401    0.355 base.py:467(save_base)
16645/12553    0.119    0.000  557.543    0.044 dispatcher.py:149(send)
     1023    0.184    0.000  557.198    0.545 indexes.py:194(update_object)
     1023    0.082    0.000  557.004    0.544 whoosh_backend.py:167(update)
     1023    0.012    0.000  477.258    0.467 writing.py:460(commit)
     1023    0.055    0.000  477.246    0.467 filewriting.py:471(commit)
     1023    0.049    0.000  239.220    0.234 filewriting.py:420(_merge_segments)
     1023    0.119    0.000  239.171    0.234 filewriting.py:52(MERGE_SMALL)
     1023    0.023    0.000  233.680    0.228 filewriting.py:322(add_reader)
     1023    2.728    0.003  227.074    0.222 filewriting.py:314(_merge_fields)
     1023    0.022    0.000  214.986    0.210 filewriting.py:434(_flush_segment)
     1023    6.380    0.006  214.714    0.210 base.py:122(add_postings)
   594686    2.748    0.000  212.403    0.000 filewriting.py:120(renumber_postings)
   594686   11.993    0.000  209.655    0.000 reading.py:334(iter_postings)
   323372    9.872    0.000  161.101    0.000 whoosh2.py:332(finish_term)
   347323    4.277    0.000  149.246    0.000 filereading.py:253(postings)
   347323    4.046    0.000  138.951    0.000 whoosh2.py:518(matcher)
   323780    3.511    0.000   83.389    0.000 whoosh2.py:283(_write_block)
   347323    3.574    0.000   68.475    0.000 filetables.py:500(__getitem__)
   340407    5.655    0.000   65.744    0.000 whoosh2.py:383(__init__)
   323780   14.767    0.000   60.635    0.000 whoosh2.py:977(to_file)
     1023    0.010    0.000   58.628    0.057 writing.py:448(update_document)
     1023    0.391    0.000   58.618    0.057 writing.py:424(_record)
     1023    0.046    0.000   58.223    0.057 writing.py:294(update_document)
   680720    3.664    0.000   55.225    0.000 whoosh2.py:421(_next_block)
   323372    3.185    0.000   51.022    0.000 filetables.py:489(add)
     9515    0.543    0.000   47.780    0.005 filereading.py:47(__init__)
     1023    0.023    0.000   44.366    0.043 writing.py:164(searcher)
     1023    0.024    0.000   43.054    0.042 filewriting.py:236(reader)
     1023    0.059    0.000   43.027    0.042 fileindex.py:280(_reader)
     8492    0.092    0.000   42.870    0.005 fileindex.py:302(segreader)
   347323    2.555    0.000   42.193    0.000 filetables.py:247(__getitem__)
   687730    4.281    0.000   39.637    0.000 filetables.py:257(all)
9951309/8590811   22.537    0.000   38.633    0.000 {len}
     9515    0.119    0.000   35.230    0.004 whoosh2.py:81(terms_reader)
   340952    2.570    0.000   34.573    0.000 whoosh2.py:410(_read_block)
     9515    0.233    0.000   32.659    0.003 whoosh2.py:497(__init__)
     9515    0.058    0.000   32.151    0.003 filetables.py:497(__init__)
     9515    0.167    0.000   32.093    0.003 filetables.py:374(__init__)
   687730   10.470    0.000   31.786    0.000 filetables.py:284(ranges_for_key)
     9515   15.358    0.002   31.729    0.003 filetables.py:174(__init__)
   340952   13.749    0.000   31.289    0.000 whoosh2.py:997(from_file)
   323372    1.568    0.000   28.919    0.000 filetables.py:121(add)
   340493    2.557    0.000   28.128    0.000 filereading.py:177(<genexpr>)
   323372   11.940    0.000   27.352    0.000 filetables.py:330(add_all)
     1931    0.018    0.000   26.902    0.014 __init__.py:48(_commit)
     1931   26.885    0.014   26.885    0.014 {method 'commit' of '_mysql.connection' objects}
     1665    0.021    0.000   24.418    0.015 transaction.py:113(commit_unless_managed)
     1665    0.032    0.000   24.375    0.015 __init__.py:197(commit_unless_managed)
   340493    2.298    0.000   22.983    0.000 filetables.py:528(keys)
  2122926   13.627    0.000   22.812    0.000 filetables.py:211(read)
   669658    4.756    0.000   22.646    0.000 whoosh2.py:322(add)
     3458    0.078    0.000   20.540    0.006 query.py:353(get)
   323372    3.052    0.000   20.101    0.000 whoosh2.py:313(start_term)
     1023    0.031    0.000   17.791    0.017 indexes.py:155(full_prepare)
     1023    0.087    0.000   17.737    0.017 indexes.py:133(prepare)
     6138    0.108    0.000   17.476    0.003 fields.py:67(prepare)
     4092    0.039    0.000   17.417    0.004 fields.py:152(prepare)
   340952    2.456    0.000   16.987    0.000 whoosh2.py:416(_consume_block)
     1023    0.023    0.000   16.835    0.016 filewriting.py:439(_close_segment)
   340407    2.512    0.000   16.728    0.000 whoosh2.py:548(valuedecoder)
1119837/1074825    2.918    0.000   16.496    0.000 {hasattr}
     1023    0.013    0.000   15.425    0.015 whoosh2.py:373(close)
     1023    0.805    0.001   15.392    0.015 whoosh2.py:482(close)
   323372    1.483    0.000   14.691    0.000 whoosh2.py:479(valuecoder)
   323780    6.538    0.000   14.479    0.000 base.py:461(add_block)
    13090    0.724    0.000   14.304    0.001 query.py:235(clone)
    15420    0.152    0.000   14.272    0.001 related.py:331(__get__)
  6563990   14.246    0.000   14.246    0.000 {method 'read' of 'cStringIO.StringI' objects}
   323372    4.006    0.000   14.046    0.000 whoosh2.py:289(_start_blocklist)
   340407    6.576    0.000   13.544    0.000 base.py:507(from_string)
   669658    8.147    0.000   13.411    0.000 filewriting.py:97(add)
        1    0.021    0.021   13.269   13.269 phpbb2djangobb.py:468(migrate_topic)
   323372    5.741    0.000   13.208    0.000 base.py:477(to_string)
   340493    2.197    0.000   12.944    0.000 filetables.py:237(keys)
    12059    0.174    0.000   12.917    0.001 query.py:853(_clone)
  4868208   12.803    0.000   12.803    0.000 {method 'write' of 'file' objects}
  5375697   12.716    0.000   12.716    0.000 {method 'unpack' of 'Struct' objects}
251017/52360    3.970    0.000   12.450    0.000 copy.py:145(deepcopy)
     2046    0.023    0.000   12.272    0.006 util.py:159(feed)
     4092    1.795    0.000   12.229    0.003 HTMLParser.py:140(goahead)
     2046    0.012    0.000   12.226    0.006 HTMLParser.py:107(feed)
   323780    4.239    0.000   12.081    0.000 base.py:767(minimize_ids)
     8559    0.268    0.000   12.041    0.001 query.py:231(iterator)
  5938888   12.003    0.000   12.003    0.000 {method 'append' of 'list' objects}
   340952    3.343    0.000   11.838    0.000 whoosh2.py:1014(read_ids)
   974616    6.490    0.000   11.543    0.000 structfile.py:231(write_uint)
     1023    0.022    0.000   11.467    0.011 util.py:216(convert_text_to_html)
     4782    0.118    0.000   11.355    0.002 compiler.py:794(execute_sql)
     1023    0.648    0.001   11.047    0.011 filewriting.py:342(add_document)
     3477    0.073    0.000   10.747    0.003 query.py:77(__len__)
   670695    6.011    0.000   10.617    0.000 filetables.py:52(md5_hash)
     8672    0.178    0.000   10.591    0.001 compiler.py:751(results_iter)
   669658    6.250    0.000   10.462    0.000 base.py:746(add)
...
     1052    0.020    0.000    0.316    0.000 utils.py:112(clean_bbcode)
...
     1052    0.013    0.000    0.146    0.000 utils.py:102(phpbb_html2bbcode)
...
     1254    0.009    0.000    0.142    0.000 utils.py:85(replace_all)
...
     2046    0.027    0.000    0.061    0.000 utils.py:87(replace_entity)
...
Anscheinend baut whoosh auch gleich den Suchindex auf. Das könnte man sich eigentlich erst mal sparen. Zumal whoosh produktiv am besten von einem anderen backend ersetzt wird.

Die Geschichte um bbcode-cleanup scheint vergleichsweise schnell zu sehen:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

jens hat geschrieben:Alles ab cumtime > 10 mit einem zusammen-gelöschtem Datensatz:

Code: Alles auswählen

...
 *** 202 topics migrated in 13.0 sec (rate: 15.6/sec) 
...
 *** 1024 posts migrated in 10.0 min (rate: 1.7/sec) 
...
         116963147 function calls (115264047 primitive calls) in 629.339 seconds
Anscheinend baut whoosh auch gleich den Suchindex auf.
Ha, das ist es! Mit https://github.com/jedie/django-phpBB3/ ... 47b7029b66 also ohne search index, sieht das schon viel besser aus 21.1/sec statt nur 1.7/sec !

Selbe Liste mit cumtime>5 :

Code: Alles auswählen

...
 *** 202 topics migrated in 13.6 sec (rate: 14.8/sec)
...
 *** 1024 posts migrated in 48.5 sec (rate: 21.1/sec)
...
         7474957 function calls (7292772 primitive calls) in 76.392 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   76.393   76.393 manage.py:2(<module>)
        1    0.000    0.000   76.329   76.329 __init__.py:438(execute_from_command_line)
        1    0.000    0.000   76.329   76.329 __init__.py:340(execute)
        1    0.000    0.000   74.539   74.539 base.py:187(run_from_argv)
        1    0.000    0.000   74.536   74.536 base.py:198(execute)
        1    0.000    0.000   74.385   74.385 phpbb2djangobb.py:101(handle)
        1    0.008    0.008   74.385   74.385 phpbb2djangobb.py:110(_handle)
        1    0.087    0.087   47.761   47.761 phpbb2djangobb.py:561(migrate_posts)
     1225    0.038    0.000   43.821    0.036 manager.py:136(create)
     1225    0.027    0.000   43.620    0.036 query.py:370(create)
     1023    0.039    0.000   39.232    0.038 models.py:219(save)
     1665    0.019    0.000   38.441    0.023 base.py:452(save)
     1665    0.136    0.000   38.422    0.023 base.py:467(save_base)
     1925    0.018    0.000   31.615    0.016 __init__.py:48(_commit)
     1925   31.597    0.016   31.597    0.016 {method 'commit' of '_mysql.connection' objects}
     1665    0.020    0.000   29.653    0.018 transaction.py:113(commit_unless_managed)
     1665    0.033    0.000   29.611    0.018 __init__.py:197(commit_unless_managed)
        1    0.024    0.024   13.442   13.442 phpbb2djangobb.py:475(migrate_topic)
     2046    0.023    0.000   12.089    0.006 util.py:159(feed)
     4092    1.760    0.000   12.048    0.003 HTMLParser.py:140(goahead)
     2046    0.013    0.000   12.047    0.006 HTMLParser.py:107(feed)
     1023    0.021    0.000   11.367    0.011 util.py:216(convert_text_to_html)
        1    0.017    0.017    9.449    9.449 phpbb2djangobb.py:674(update_topic_stats)
     1412    0.032    0.000    9.049    0.006 query.py:353(get)
     6938    0.389    0.000    7.880    0.001 query.py:235(clone)
     2723    0.066    0.000    7.142    0.003 compiler.py:794(execute_sql)
138319/27752    2.193    0.000    6.891    0.000 copy.py:145(deepcopy)
     1023    0.015    0.000    6.586    0.006 util.py:164(urlize)
     1026    0.028    0.000    6.536    0.006 manager.py:130(get)
     4432    0.136    0.000    6.458    0.001 query.py:231(iterator)
     5913    0.087    0.000    6.361    0.001 query.py:853(_clone)
     4545    0.085    0.000    5.633    0.001 compiler.py:751(results_iter)
     1023    0.013    0.000    5.605    0.005 util.py:182(smiles)
184769/165458    0.378    0.000    5.437    0.000 {len}
     1431    0.031    0.000    5.142    0.004 query.py:77(__len__)
...
EDIT: Nun profile stats ohne das löschen der DjangoBB Tabellen.

Was könnte man da noch optimieren???


EDIT2: So, nun sind auf dem produktiv Server rund 100 posts / sec drin. (Lokal bei mir greift eine VM mit dem Migrationsskript auf den MySQL Server in einer anderen VM zu. Deswegen nur 21.1/sec ;)
In der Praxis bedeutet das, die Migration ist in ca. 30Min fertig, statt vorher in 8h :shock:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Nächstes Problem:

Code: Alles auswählen

  File "/home/jedie/DjangoBB_env/src/django-phpbb3/django_phpBB3/management/commands/phpbb2djangobb.py", line 610, in migrate_posts
    user_ip=phpbb_post.poster_ip,
  File "/home/jedie/DjangoBB_env/lib/python2.6/site-packages/django/db/models/manager.py", line 137, in create
    return self.get_query_set().create(**kwargs)
  File "/home/jedie/DjangoBB_env/lib/python2.6/site-packages/django/db/models/query.py", line 377, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/jedie/DjangoBB_env/src/djangobb/djangobb_forum/models.py", line 222, in save
    self.body_html = smiles(self.body_html)
  File "/home/jedie/DjangoBB_env/src/djangobb/djangobb_forum/util.py", line 188, in smiles
    parser.feed(data)
  File "/home/jedie/DjangoBB_env/src/djangobb/djangobb_forum/util.py", line 160, in feed
    HTMLParser.feed(self, data)
  File "/usr/lib64/python2.6/HTMLParser.py", line 108, in feed
    self.goahead(0)
  File "/usr/lib64/python2.6/HTMLParser.py", line 148, in goahead
    k = self.parse_starttag(i)
  File "/usr/lib64/python2.6/HTMLParser.py", line 229, in parse_starttag
    endpos = self.check_for_whole_start_tag(i)
  File "/usr/lib64/python2.6/HTMLParser.py", line 304, in check_for_whole_start_tag
    self.error("malformed start tag")
  File "/usr/lib64/python2.6/HTMLParser.py", line 115, in error
    raise HTMLParseError(message, self.getpos())
HTMLParseError: malformed start tag, at line 1, column 155
bei: http://www.python-forum.de/viewtopic.php?p=74377#p74377

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Warum wird da irgendwelches HTML geparsed?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das passiert im code Teil von DjangoBB beim speichern eines neuen Beitragt:

Code: Alles auswählen

class Post(models.Model):
...
    def save(self, *args, **kwargs):
        self.body_html = convert_text_to_html(self.body, self.markup)
        if forum_settings.SMILES_SUPPORT and self.user.forum_profile.show_smilies:
            self.body_html = smiles(self.body_html)
        super(Post, self).save(*args, **kwargs)
Bei DjangoBB wird einmal der Text eines Beitrags als "roh"-Markup und einmal als gerenderter HTML-Code gespeichert.

Die SMILES_SUPPORT ist der Übeltäter. Im Grunde werden Text Smilies durch Bilder ersetzt.
Wenn ich https://github.com/slav0nic/DjangoBB/bl ... um/util.py richtig verstanden hab, wird HTMLParser genutzt um Smilies nicht in 'a', 'pre' und 'span' Bereiche zu ersetzten.

HTMLParser hat ein paar Probleme, wenn der HTML nicht ganz sauber ist. Ich konnte allerdings den Fehler lokal nicht reproduzieren.

Frage mich nun, ob man in DjangoBB eine andere Lösung suchen sollte: Kann man dort überhaupt diesen Fehler provozieren? Oder kann man nur in phpBB "defekten" HTML code über bbcode produzieren.
Vielleicht liegt der Fehler auch in der postmarkup Bibliothek.

EDIT: Bei meiner DjangoBB installation konnte ich keinen Fehler Provozieren: http://www.pylucid.org/de/forum/topic/356/
Den Migrationstest hatte ich allerdings auch mit Python 2.6.6 gemacht (Wobei die letzte 2.6.x Release ist 2.6.8). Auf meinem Server läuft 2.7.3
Evtl. liegt es an einer älteren Version von HTMLParser. Auf http://bugs.python.org/issue findet man einige Einträge, wenn man einfach nach "HTMLParser" sucht...
Vielleicht sollte man einfach HTMLParseError abfangen wenn settings.DEBUG==False und die Smilies einfach als Text belassen.
Eigentlich ist es eh ein wenig Blöd, wenn man die Pfade Hardcoded. Man müsste eine Migration machen, wenn man die URL der statischen Dateien ändert.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

jens hat geschrieben:Das passiert im code Teil von DjangoBB beim speichern eines neuen Beitragt:

Code: Alles auswählen

class Post(models.Model):
...
    def save(self, *args, **kwargs):
        self.body_html = convert_text_to_html(self.body, self.markup)
        if forum_settings.SMILES_SUPPORT and self.user.forum_profile.show_smilies:
            self.body_html = smiles(self.body_html)
        super(Post, self).save(*args, **kwargs)
Bei DjangoBB wird einmal der Text eines Beitrags als "roh"-Markup und einmal als gerenderter HTML-Code gespeichert.
Ok, und warum ist da HTML? Mir kommt das nicht vor als wäre das eine gute Idee, in der Datenbank irgendwelches HTML abzulegen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich hab's. Es liegt am HTMLParser von 2.6... In 2.7 ist alles ok.

Hier ein paar Tests:

[url="foo"bar"]one foo"bar :)[/url] A"B :D
[url="foo".bar"]two foo".bar :)[/url] A".B :D
[url="foo."bar"]three foo."bar :)[/url] A."B :D
[url="foo.".bar"]four foo.".bar :)[/url] A.".B :D

Hiermit kann man es nachvollziehen:

Code: Alles auswählen

import sys
from HTMLParser import HTMLParser

print sys.version

tests=(
	'<a href="foo"bar"></a>',
	'<a href="foo".bar"></a>',
	'<a href="foo."bar"></a>',
	'<a href="foo.".bar"></a>',
)

for html in tests:
	print
	print repr(html)
	parser = HTMLParser()
	try:
		parser.feed(html)
		parser.close()
	except Exception, err:
		print "Error: %s" % err
	else:
		print "OK"

print "--END--"
Ausgabe 1:

Code: Alles auswählen

2.7.3 (default, Aug  1 2012, 05:14:39) 
[GCC 4.6.3]

'<a href="foo"bar"></a>'
OK

'<a href="foo".bar"></a>'
OK

'<a href="foo."bar"></a>'
OK

'<a href="foo.".bar"></a>'
OK
--END--
Ausgabe 2:

Code: Alles auswählen

2.6.6 (r266:84292, Sep 11 2012, 08:34:23) 
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)]

'<a href="foo"bar"></a>'
Error: EOF in middle of construct, at line 1, column 1

'<a href="foo".bar"></a>'
Error: malformed start tag, at line 1, column 14

'<a href="foo."bar"></a>'
Error: EOF in middle of construct, at line 1, column 1

'<a href="foo.".bar"></a>'
Error: malformed start tag, at line 1, column 15
--END--

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Leonidas hat geschrieben:Ok, und warum ist da HTML? Mir kommt das nicht vor als wäre das eine gute Idee, in der Datenbank irgendwelches HTML abzulegen.
Das ist ein anderes Thema ;)

Es ist halt eine einfache Form eines Caches. Ansonsten müsste man immer on-the-fly markup -> html erzeugen. Kann man natürlich auch. Würde aber den Server stärker belasten.

Den einzigen Knackpunkt den ich hier sehe, wäre das mit dem ändern der Smilies. Aber eine migration in diesem Falle wäre einfach:

Code: Alles auswählen

for post in Post.objects.all():
    post.save()

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten